3

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. }

19
  • 10
    Probably because the set of Java programmers who need a complex number class is vanishingly small. Note that the C++ support for this is just a library, nothing like native support as a base type. That's a whole different ball of wax from what you link to, which is compiler support. (Unless someone has design docs or quotes, this is an opinion question, unfortunately.) Apr 4, 2016 at 20:53
  • 2
    Why isn't there a "quaternian number" type in java? What about "octonian number" types? These seem like a no-brainer... I realize the java gawds dont want to turn java into math but this is a thing that math handles beautifully and this guys implementation (written centurys years ago!!!1) handles excellently but is now hopelessly out of date to be of practical use Apr 4, 2016 at 22:57
  • 4
    I think it's worth noting that, in hindsight, primitives were a mistake in Java. They really should have been implemented as Object types with compiler optimizations.
    – JimmyJames
    Apr 5, 2016 at 0:31
  • 1
    Jimmy, that's not possible. GC spam. Millions of new objects per matrix multiply is just insane. Or, can java magically see into the future and just know how the object is going to be used later on. It's like physicists and their spherical cows. No, primitives were not a mistake
    – crow
    Apr 5, 2016 at 0:36
  • 3
    To quote Eric Lippert, 'the answer to every question of the form “why doesn’t product X have feature Y?” is the same. It’s because in order for a product to have a feature, that feature must be thought of in the first place, desired, designed, specified, implemented, tested, documented, [and] shipped to customers. You’ve got to hit every single one of those things, otherwise, no feature. ' In this case, because Java is not primarily aimed at scientific programmers, the idea fails at the second point.
    – Jules
    Apr 5, 2016 at 7:31

4 Answers 4

13

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.

7
  • 2
    "allow us to remove all 8 primitives ..." Not to mention the ugly string concatenation hack.
    – Jules
    Apr 5, 2016 at 7:16
  • It's not a proper programming language if it doesn't support imaginary numbers!
    – GordonM
    Apr 5, 2016 at 9:24
  • What is the source for the Java 11 reference?
    – soandos
    Apr 5, 2016 at 14:27
  • @soandos: A guess. They were already talked about for Java 8, pushed from Java 9, but there are already quite a number of talks and papers about them, and Oracle seems seriously committed to them. Add one version just to be safe and you end up with Java 11. Apr 5, 2016 at 14:40
  • Nice joke about tasteful SBT DSL
    – Basilevs
    May 25, 2016 at 16:55
7

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.

4

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.

1
  • +1 - This is the answer to the question as asked. Jörg makes interesting points about there being better solutions, but the real answer is simply that this is outside of the scope for the kind of application Java was designed for.
    – Jules
    Apr 5, 2016 at 7:24
0

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.)

10
  • Surely it's perfectly suited to an object rather than a struct; with complexConjugate(), magnitude() methods etc. I can't really think of anything that a struct is good for other than being a poor man's object Apr 4, 2016 at 21:01
  • 2
    @RichardTingle You seem to be operating from the premise that an object can have methods and a struct can't. What makes you think this? The essential difference between an object and a struct is that an object is a reference type and can have inheritance, while a struct is a value type and cannot have inheritance. Apr 4, 2016 at 21:07
  • 1
    A complex number is not a grouping of two distinct numbers (a.k.a., an ordered pair.) A complex number can be represented by an ordered pair, but so can the location of a point in a photograph, or the location of a point on the surface of the Earth, or a sample of the outdoor air temperature at a particular time, or your weight and height. But, the set of operations that can be performed on each of those examples is different: They are different data types. Apr 4, 2016 at 21:20
  • @Mason it is true that what a struct is can vary based on language (I can quote languages where a struct is exactly that; a collection of data, nothing else). However the point is that you seem to quite heavily imply that a struct would be superior to a (probably immutable) object for complex numbers. Apr 4, 2016 at 21:24
  • 2
    @MasonWheeler well you can't represent a floating point number as a single number either, the java team just chose a standard and went with it. I really fail to see how "is two numbers" is a problem, do you think it'll be an issue when it comes to memory allocation? also, you can express complex numbers as e^(ϕi), similar to how store floats.
    – sara
    Apr 5, 2016 at 11:08

Not the answer you're looking for? Browse other questions tagged or ask your own question.