1 package org.djunits.value.vdouble.scalar.base;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5 import java.util.HashMap;
6 import java.util.Map;
7
8 import org.djunits.unit.AbsoluteLinearUnit;
9 import org.djunits.unit.SIUnit;
10 import org.djunits.unit.Unit;
11 import org.djunits.unit.si.SIPrefixes;
12 import org.djunits.unit.util.UnitRuntimeException;
13 import org.djunits.value.Absolute;
14 import org.djunits.value.base.Scalar;
15 import org.djunits.value.formatter.Format;
16 import org.djunits.value.util.ValueUtil;
17 import org.djunits.value.vdouble.scalar.SIScalar;
18
19
20
21
22
23
24
25
26
27
28
29
30 public abstract class DoubleScalar<U extends Unit<U>, S extends DoubleScalar<U, S>> extends Scalar<U, S>
31 {
32
33 private static final long serialVersionUID = 20161015L;
34
35
36 @SuppressWarnings("checkstyle:visibilitymodifier")
37 public final double si;
38
39
40
41
42
43
44 public DoubleScalar(final U unit, final double si)
45 {
46 super(unit);
47 this.si = si;
48 }
49
50
51
52
53
54 public final double getSI()
55 {
56 return this.si;
57 }
58
59
60
61
62
63 public final double getInUnit()
64 {
65 return ValueUtil.expressAsUnit(getSI(), getDisplayUnit());
66 }
67
68
69
70
71
72
73 public final double getInUnit(final U targetUnit)
74 {
75 return ValueUtil.expressAsUnit(getSI(), targetUnit);
76 }
77
78 @Override
79 public final boolean lt(final S o)
80 {
81 return this.getSI() < o.getSI();
82 }
83
84 @Override
85 public final boolean le(final S o)
86 {
87 return this.getSI() <= o.getSI();
88 }
89
90 @Override
91 public final boolean gt(final S o)
92 {
93 return this.getSI() > o.getSI();
94 }
95
96 @Override
97 public final boolean ge(final S o)
98 {
99 return this.getSI() >= o.getSI();
100 }
101
102 @Override
103 public final boolean eq(final S o)
104 {
105 return this.getSI() == o.getSI();
106 }
107
108 @Override
109 public final boolean ne(final S o)
110 {
111 return this.getSI() != o.getSI();
112 }
113
114 @Override
115 public final boolean lt0()
116 {
117 return this.getSI() < 0.0;
118 }
119
120 @Override
121 public final boolean le0()
122 {
123 return this.getSI() <= 0.0;
124 }
125
126 @Override
127 public final boolean gt0()
128 {
129 return this.getSI() > 0.0;
130 }
131
132 @Override
133 public final boolean ge0()
134 {
135 return this.getSI() >= 0.0;
136 }
137
138 @Override
139 public final boolean eq0()
140 {
141 return this.getSI() == 0.0;
142 }
143
144 @Override
145 public final boolean ne0()
146 {
147 return this.getSI() != 0.0;
148 }
149
150 @Override
151 public final int compareTo(final S o)
152 {
153 return Double.compare(this.getSI(), o.getSI());
154 }
155
156 @Override
157 public int intValue()
158 {
159 return (int) this.getSI();
160 }
161
162 @Override
163 public long longValue()
164 {
165 return (long) this.getSI();
166 }
167
168 @Override
169 public float floatValue()
170 {
171 return (float) this.getSI();
172 }
173
174 @Override
175 public double doubleValue()
176 {
177 return this.getSI();
178 }
179
180
181
182
183
184 @Override
185 public String toString()
186 {
187 return toString(getDisplayUnit(), false, true);
188 }
189
190 @Override
191 public String toString(final U displayUnit)
192 {
193 return toString(displayUnit, false, true);
194 }
195
196 @Override
197 public String toString(final boolean verbose, final boolean withUnit)
198 {
199 return toString(getDisplayUnit(), verbose, withUnit);
200 }
201
202 @Override
203 public String toString(final U displayUnit, final boolean verbose, final boolean withUnit)
204 {
205 StringBuffer buf = new StringBuffer();
206 if (verbose)
207 {
208 buf.append(this instanceof Absolute ? "Abs " : "Rel ");
209 }
210 double d = ValueUtil.expressAsUnit(getSI(), displayUnit);
211 buf.append(Format.format(d));
212 if (withUnit)
213 {
214 buf.append(" ");
215 buf.append(displayUnit.getLocalizedDisplayAbbreviation());
216 }
217 return buf.toString();
218 }
219
220
221
222
223
224
225 public String toStringSIPrefixed()
226 {
227 return toStringSIPrefixed(-24, 26);
228 }
229
230
231
232
233
234
235
236
237 public String toStringSIPrefixed(final int smallestPower, final int biggestPower)
238 {
239
240 if (!Double.isFinite(this.si))
241 {
242 return toString(getDisplayUnit().getStandardUnit());
243 }
244
245
246 String check = String.format(this.si >= 0 ? "%10.8E" : "%10.7E", this.si);
247 int exponent = Integer.parseInt(check.substring(check.indexOf("E") + 1));
248 if (exponent < -24 || exponent < smallestPower || exponent > 24 + 2 || exponent > biggestPower)
249 {
250
251 return String.format(this.si >= 0 ? "%10.4E" : "%10.3E", this.si) + " "
252 + getDisplayUnit().getStandardUnit().getId();
253 }
254 Integer roundedExponent = (int) Math.ceil((exponent - 2.0) / 3) * 3;
255
256 String key =
257 SIPrefixes.FACTORS.get(roundedExponent).getDefaultTextualPrefix() + getDisplayUnit().getStandardUnit().getId();
258 U displayUnit = getDisplayUnit().getQuantity().getUnitByAbbreviation(key);
259 return toString(displayUnit);
260 }
261
262 @Override
263 public String toTextualString()
264 {
265 return toTextualString(getDisplayUnit());
266 }
267
268 @Override
269 public String toTextualString(final U displayUnit)
270 {
271 double d = ValueUtil.expressAsUnit(getSI(), displayUnit);
272 return format(d) + " " + displayUnit.getLocalizedTextualAbbreviation();
273 }
274
275 @Override
276 public String toDisplayString()
277 {
278 return toDisplayString(getDisplayUnit());
279 }
280
281 @Override
282 public String toDisplayString(final U displayUnit)
283 {
284 double d = ValueUtil.expressAsUnit(getSI(), displayUnit);
285 return format(d) + " " + displayUnit.getLocalizedDisplayAbbreviation();
286 }
287
288 @Override
289 @SuppressWarnings("checkstyle:designforextension")
290 public int hashCode()
291 {
292 final int prime = 31;
293 int result = getDisplayUnit().getStandardUnit().hashCode();
294 long temp;
295 temp = Double.doubleToLongBits(this.getSI());
296 result = prime * result + (int) (temp ^ (temp >>> 32));
297 return result;
298 }
299
300 @Override
301 @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces", "unchecked"})
302 public boolean equals(final Object obj)
303 {
304 if (this == obj)
305 return true;
306 if (obj == null)
307 return false;
308 if (getClass() != obj.getClass())
309 return false;
310 DoubleScalar<U, S> other = (DoubleScalar<U, S>) obj;
311 if (!getDisplayUnit().getStandardUnit().equals(other.getDisplayUnit().getStandardUnit()))
312 return false;
313 if (Double.doubleToLongBits(this.getSI()) != Double.doubleToLongBits(other.getSI()))
314 return false;
315 return true;
316 }
317
318
319
320
321
322
323 private static final Map<Unit<?>, Constructor<? extends DoubleScalar<?, ?>>> CACHE = new HashMap<>();
324
325
326
327
328
329
330
331
332
333 public static <U extends Unit<U>, S extends DoubleScalar<U, S>> S instantiate(final double value, final U unit)
334 {
335 return instantiateAnonymous(value, unit);
336 }
337
338
339
340
341
342
343
344
345
346 public static <U extends Unit<U>, S extends DoubleScalar<U, S>> S instantiateSI(final double valueSI,
347 final U displayUnit)
348 {
349 S result = instantiateAnonymous(valueSI, displayUnit.getStandardUnit());
350 result.setDisplayUnit(displayUnit);
351 return result;
352 }
353
354
355
356
357
358
359
360
361
362
363 @SuppressWarnings("unchecked")
364 public static <S extends DoubleScalar<?, S>> S instantiateAnonymous(final double value, final Unit<?> unit)
365 {
366 try
367 {
368 Constructor<? extends DoubleScalar<?, ?>> scalarConstructor = CACHE.get(unit);
369 if (scalarConstructor == null)
370 {
371 if (!unit.getClass().getSimpleName().endsWith("Unit"))
372 {
373 throw new ClassNotFoundException("Unit " + unit.getClass().getSimpleName()
374 + " name does noet end with 'Unit'. Cannot find corresponding scalar");
375 }
376 Class<? extends DoubleScalar<?, ?>> scalarClass;
377 if (unit instanceof SIUnit)
378 {
379 scalarClass = SIScalar.class;
380 }
381 else
382 {
383 scalarClass = (Class<DoubleScalar<?, ?>>) Class
384 .forName("org.djunits.value.vdouble.scalar." + unit.getClass().getSimpleName().replace("Unit", ""));
385 }
386 scalarConstructor = scalarClass.getDeclaredConstructor(double.class, unit.getClass());
387 CACHE.put(unit, scalarConstructor);
388 }
389 return (S) scalarConstructor.newInstance(value, unit);
390 }
391 catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
392 | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception)
393 {
394 throw new UnitRuntimeException("Cannot instantiate DoubleScalar of unit " + unit.toString() + ". Reason: "
395 + exception.getMessage());
396 }
397 }
398
399
400
401
402
403
404
405
406
407
408
409
410 public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
411 R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
412 A extends DoubleScalarAbs<AU, A, RU, R>> A plus(final A left, final R right)
413 {
414 return left.plus(right);
415 }
416
417
418
419
420
421
422
423
424
425
426
427
428 public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
429 R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
430 A extends DoubleScalarAbs<AU, A, RU, R>> A plus(final R left, final A right)
431 {
432 return right.plus(left);
433 }
434
435
436
437
438
439
440
441
442
443
444 public static <U extends Unit<U>, R extends DoubleScalarRel<U, R>> R plus(final R left, final R right)
445 {
446 return left.plus(right);
447 }
448
449
450
451
452
453
454
455
456
457
458
459
460 public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
461 R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
462 A extends DoubleScalarAbs<AU, A, RU, R>> A minus(final A left, final R right)
463 {
464 return left.minus(right);
465 }
466
467
468
469
470
471
472
473
474
475
476 public static <U extends Unit<U>, R extends DoubleScalarRel<U, R>> R minus(final R left, final R right)
477 {
478 return left.minus(right);
479 }
480
481
482
483
484
485
486
487
488
489
490
491
492 public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
493 R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
494 A extends DoubleScalarAbs<AU, A, RU, R>> R minus(final A left, final A right)
495 {
496 return left.minus(right);
497 }
498
499
500
501
502
503
504
505 public static SIScalar multiply(final DoubleScalarRel<?, ?> left, final DoubleScalarRel<?, ?> right)
506 {
507 SIUnit targetUnit = Unit.lookupOrCreateUnitWithSIDimensions(left.getDisplayUnit().getQuantity().getSiDimensions()
508 .plus(right.getDisplayUnit().getQuantity().getSiDimensions()));
509 return new SIScalar(left.getSI() * right.getSI(), targetUnit);
510 }
511
512
513
514
515
516
517
518 public static SIScalar divide(final DoubleScalarRel<?, ?> left, final DoubleScalarRel<?, ?> right)
519 {
520 SIUnit targetUnit = Unit.lookupOrCreateUnitWithSIDimensions(left.getDisplayUnit().getQuantity().getSiDimensions()
521 .minus(right.getDisplayUnit().getQuantity().getSiDimensions()));
522 return new SIScalar(left.getSI() / right.getSI(), targetUnit);
523 }
524
525
526
527
528
529
530
531
532
533
534 public static <U extends Unit<U>, R extends DoubleScalarRel<U, R>> R interpolate(final R zero, final R one,
535 final double ratio)
536 {
537 return zero.instantiateRel(zero.getInUnit() * (1 - ratio) + one.getInUnit(zero.getDisplayUnit()) * ratio,
538 zero.getDisplayUnit());
539 }
540
541
542
543
544
545
546
547
548
549
550
551
552 public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
553 R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
554 A extends DoubleScalarAbs<AU, A, RU, R>> A interpolate(final A zero, final A one, final double ratio)
555 {
556 return zero.instantiateAbs(zero.getInUnit() * (1 - ratio) + one.getInUnit(zero.getDisplayUnit()) * ratio,
557 zero.getDisplayUnit());
558 }
559
560
561
562
563
564
565
566
567
568 public static <U extends Unit<U>, T extends DoubleScalar<U, T>> T max(final T r1, final T r2)
569 {
570 return (r1.gt(r2)) ? r1 : r2;
571 }
572
573
574
575
576
577
578
579
580
581
582 @SafeVarargs
583 public static <U extends Unit<U>, T extends DoubleScalar<U, T>> T max(final T r1, final T r2, final T... rn)
584 {
585 T maxr = (r1.gt(r2)) ? r1 : r2;
586 for (T r : rn)
587 {
588 if (r.gt(maxr))
589 {
590 maxr = r;
591 }
592 }
593 return maxr;
594 }
595
596
597
598
599
600
601
602
603
604 public static <U extends Unit<U>, T extends DoubleScalar<U, T>> T min(final T r1, final T r2)
605 {
606 return r1.lt(r2) ? r1 : r2;
607 }
608
609
610
611
612
613
614
615
616
617
618 @SafeVarargs
619 public static <U extends Unit<U>, T extends DoubleScalar<U, T>> T min(final T r1, final T r2, final T... rn)
620 {
621 T minr = r1.lt(r2) ? r1 : r2;
622 for (T r : rn)
623 {
624 if (r.lt(minr))
625 {
626 minr = r;
627 }
628 }
629 return minr;
630 }
631
632 }