Question

Does anyone know why something like cj library for complex numbers was never completed and integrated into mainline Java?

This seems like a no-brainer... I realize the Java gawds don't want to turn Java into C++ but this is a thing that C++ handles beautifully and this guy's implementation (written 17 years ago!) handles excellently but is now hopelessly out of date to be of practical use.

Yes. Add quaternions and octonions too. But that's all. I'm not suggesting a Pandora's box. The real, complex, quaternionic, and octonionionic numbers are the only normed division algebras. You could argue against that though, staying in the realm of * always being commutative as far as order of operations is concerned. Go back and read the article I linked to in the OP. Spawning millions of temporary objects to spam the GC is wasteful and makes Java jot suitable for some tasks that it could be easily made to be suitable. The thing that distinguishes a primitive is that it is a unit, and not a pointer to a heap. If you go that OO extreme you might as well join the camp that is saying double primitives should be done away with too. Yes what I'm suggesting amounts to a builtin operator that compiles to byte codes that is complete standard and maps to a pair of doubles. See the cj implementation and README I linked to. Full blown operator overloading would be a mess but this easily doable.

I am not suggesting only extension of language to complex types.

For my ideas, see the article I wrote up summarizing this book about Clifford Algebras

http://vixra.org/abs/1203.0011

For instance, complex data types are central to quantum computing.. but also, the comment below about the user-defined types, while neat, does not lend itself to stringing together high-performance complex (no pun intended) code which can be spun on the fly by the jvm or whatever hardware, quantum, classical, or otherwise... already thinking ahead here.. and no, this is not a proliferation of messing up "java purity" but is actually the rigorous, scientific, etc, e.g. GOOD, way of doing things.. it opens up possibilities for those who can use them.

For instance, these constructs (no I didn't just pick this out of thin air, but nearly so..) sound like the perfect fit for some applications to compiler theory and turning machines and user input/output (modeled as observables as output and stochastic processes as input) ..

1.2.3. Exact Sequences, Centers, and Centralizers. A group G is simple if it has no normal subgroups other than {e} and G. The group with one element is denoted by 1 if the composition law is multiplication, or 0 if the composition law is addition. Suppose that a sequence of groups {G0 = 1, G1, , Gk, Gk+1 = 1} is given and that θj: Gj → Gj+1 is a morphism for ...then the diagram...is an exact sequence if θj−1(Gj−1) is the kernel of θj∀1 6 j 6 k. When k = 3 the sequence is a short exact sequence. }

Was it helpful?

Solution

In general, it is a bad sign if you need to change the language to add a new datatype or operation. That means that the language is lacking some feature, preventing you from expressing your program.

You are proposing to change the language and add a complex type. As @Thomas Eding hinted at above: why stop there? What about quaternions? They arise quite frequently in quantum physics and 3D graphics. They are probably even more useful than complex numbers. What about rational numbers? Real (not floating point) numbers? Natural numbers? Integers (not int modulo 232, but real arbitrary-size integers)?

No. You can't keep piling on features on top of features. The language will crumble under its own weight.

The feature we really need is Value Types. And what do you know? They are already in the works, and will probably appear in Java 11 at the latest. Value types would allow you to implement the semantics of complex as a library. And the semantics of quaternions, octonions, big decimals, rationals, tuples, structs, records, money, dates, … all without having to change the language.

I admit, it would only allow you to implement the semantics, though.

In order to implement the syntax, we would need two additional features:

  • operator overloading (already exists in the language, but not user-defined)
  • user-defined literals (exist in C++, Scala, some other languages)

Operator overloading would allow you to write c1 + c2 instead of c1.plus(c2). User-defined literals would allow you to write 2i instead of new Complex(0, 2). The combination of both would allow you to write 2 + 3i instead of new Complex(2, 3).

Maybe we'll get that. Maybe we don't. Scala has both shown that operator overloading and user-defined operators can be done very tastefully, and it also has shown that they can be overused and abused. Look at SBT's DSL for an extremely tasteful and well-balanced use of operator overloading.

The really cool thing is that if we were to get Value Types, User-Defined Literals and Operator Overloading, while that would certainly add complexity to the language, it would at the same time allow us to remove all 8 primitives from the language and implement them as a library! Which in turn would greatly simplify the language.

That's a very good sign for a good language feature: if adding it actually makes the language smaller. This is not true for your proposal, which is basically to add yet another specialized one-off type to the already existing specialized one-off primitives.

OTHER TIPS

Primitive types in programming languages abstract CPU types, which are scalars. Complex numbers are not scalars, they are aggregate types because there are two numbers.

How would you design it? Complex numbers are often used in calculations, and Java does not handle this well.

Would it be generic, to allow different size numbers? Now you have to box primitive types because Java does not allow primitive generic types. This would harm performance, given the use case for complex numbers.

Would it be a class that encapsulates two primitives, e.g. class Complex { public double r, i;}? What if you need different types, perhaps float or BigDecimal?

There is no one-size fits approach due to the nature of Java's generics. Java's standard library is already littered with obsolete classes (there are at least three ways to load an image, and one of them does not work at all). Why add a class that we already know will not work in a large number of cases?

The proper solution is to leave the type unspecified, and allow people who need one to write their own. It took me all of ten seconds in that little example above. This has the advantage that developers can weigh the tradeoffs and write it appropriately for their needs.

The built-in primitives like char, int, boolean etc. are general-purpose and useful for almost any kind of computing. Complex numbers one the other hand are pretty domain specific, and mostly used in scientific computing. There are not useful enough to justify being part of the core set of primitives. Note that Java was initially designed to be simpler than C++ and the target domain was devices and appliances, not scientific computing.

So why are complex numbers not supported on the library level then? The problem is Java does not support operator overloading, which means any kind of calculation using custom numeric types is going to be incredibly ugly. Rather than a + b * c you will have to write something like Numeric.add(a, Numeric.multiply(b, c)). But the designers of Java deliberately chose to exclude support for operator overloading because they believed it tended to lead to cryptic code. So they sacrificed a specific domain (numeric computing) in order to create a more generally productive language.

Java is simply not designed for numeric and scientific computing, and would require fundamental changes in order to be a contender in this space.

Because the concept of "complex number" is, by definition, not a primitive type. It's a grouping of two distinct real numbers, the first of which is arbitrarily designated as "the real component" and the other of which is designated as "the imaginary component".

In other words, the concept is perfectly suited to the programming concept of a struct. (Which Java also doesn't have, but that's a whole other issue.)

Licensed under: CC-BY-SA with attribution
scroll top