View Javadoc
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   * The most basic abstract class for the DoubleScalar.
21   * <p>
22   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
23   * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS License</a>.
24   * </p>
25   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
26   * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a>
27   * @param <U> the unit
28   * @param <S> the type
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      /** The value, stored in the standard SI unit. */
36      @SuppressWarnings("checkstyle:visibilitymodifier")
37      public final double si;
38  
39      /**
40       * Construct a new DoubleScalar.
41       * @param unit U; the unit
42       * @param si double; the si value to store
43       */
44      public DoubleScalar(final U unit, final double si)
45      {
46          super(unit);
47          this.si = si;
48      }
49  
50      /**
51       * Retrieve the value in the underlying SI unit.
52       * @return double
53       */
54      public final double getSI()
55      {
56          return this.si;
57      }
58  
59      /**
60       * Retrieve the value in the original unit.
61       * @return double
62       */
63      public final double getInUnit()
64      {
65          return ValueUtil.expressAsUnit(getSI(), getDisplayUnit());
66      }
67  
68      /**
69       * Retrieve the value converted into some specified unit.
70       * @param targetUnit U; the unit to convert the value into
71       * @return double
72       */
73      public final double getInUnit(final U targetUnit)
74      {
75          return ValueUtil.expressAsUnit(getSI(), targetUnit);
76      }
77  
78      /** {@inheritDoc} */
79      @Override
80      public final boolean lt(final S o)
81      {
82          return this.getSI() < o.getSI();
83      }
84  
85      /** {@inheritDoc} */
86      @Override
87      public final boolean le(final S o)
88      {
89          return this.getSI() <= o.getSI();
90      }
91  
92      /** {@inheritDoc} */
93      @Override
94      public final boolean gt(final S o)
95      {
96          return this.getSI() > o.getSI();
97      }
98  
99      /** {@inheritDoc} */
100     @Override
101     public final boolean ge(final S o)
102     {
103         return this.getSI() >= o.getSI();
104     }
105 
106     /** {@inheritDoc} */
107     @Override
108     public final boolean eq(final S o)
109     {
110         return this.getSI() == o.getSI();
111     }
112 
113     /** {@inheritDoc} */
114     @Override
115     public final boolean ne(final S o)
116     {
117         return this.getSI() != o.getSI();
118     }
119 
120     /** {@inheritDoc} */
121     @Override
122     public final boolean lt0()
123     {
124         return this.getSI() < 0.0;
125     }
126 
127     /** {@inheritDoc} */
128     @Override
129     public final boolean le0()
130     {
131         return this.getSI() <= 0.0;
132     }
133 
134     /** {@inheritDoc} */
135     @Override
136     public final boolean gt0()
137     {
138         return this.getSI() > 0.0;
139     }
140 
141     /** {@inheritDoc} */
142     @Override
143     public final boolean ge0()
144     {
145         return this.getSI() >= 0.0;
146     }
147 
148     /** {@inheritDoc} */
149     @Override
150     public final boolean eq0()
151     {
152         return this.getSI() == 0.0;
153     }
154 
155     /** {@inheritDoc} */
156     @Override
157     public final boolean ne0()
158     {
159         return this.getSI() != 0.0;
160     }
161 
162     /** {@inheritDoc} */
163     @Override
164     public final int compareTo(final S o)
165     {
166         return Double.compare(this.getSI(), o.getSI());
167     }
168 
169     /** {@inheritDoc} */
170     @Override
171     public int intValue()
172     {
173         return (int) this.getSI();
174     }
175 
176     /** {@inheritDoc} */
177     @Override
178     public long longValue()
179     {
180         return (long) this.getSI();
181     }
182 
183     /** {@inheritDoc} */
184     @Override
185     public float floatValue()
186     {
187         return (float) this.getSI();
188     }
189 
190     /** {@inheritDoc} */
191     @Override
192     public double doubleValue()
193     {
194         return this.getSI();
195     }
196 
197     /**********************************************************************************/
198     /********************************* GENERIC METHODS ********************************/
199     /**********************************************************************************/
200 
201     /** {@inheritDoc} */
202     @Override
203     public String toString()
204     {
205         return toString(getDisplayUnit(), false, true);
206     }
207 
208     /** {@inheritDoc} */
209     @Override
210     public String toString(final U displayUnit)
211     {
212         return toString(displayUnit, false, true);
213     }
214 
215     /** {@inheritDoc} */
216     @Override
217     public String toString(final boolean verbose, final boolean withUnit)
218     {
219         return toString(getDisplayUnit(), verbose, withUnit);
220     }
221 
222     /** {@inheritDoc} */
223     @Override
224     public String toString(final U displayUnit, final boolean verbose, final boolean withUnit)
225     {
226         StringBuffer buf = new StringBuffer();
227         if (verbose)
228         {
229             buf.append(this instanceof Absolute ? "Abs " : "Rel ");
230         }
231         double d = ValueUtil.expressAsUnit(getSI(), displayUnit);
232         buf.append(Format.format(d));
233         if (withUnit)
234         {
235             buf.append(" "); // Insert one space as prescribed by SI writing conventions
236             buf.append(displayUnit.getLocalizedDisplayAbbreviation());
237         }
238         return buf.toString();
239     }
240 
241     /**
242      * Format this DoubleScalar in SI unit using prefixes when possible. If the value is too small or too large,
243      * e-notation and the plain SI unit are used.
244      * @return String; formatted value of this DoubleScalar
245      */
246     public String toStringSIPrefixed()
247     {
248         return toStringSIPrefixed(-24, 26);
249     }
250 
251     /**
252      * Format this DoubleScalar in SI unit using prefixes when possible and within the specified size range. If the
253      * value is too small or too large, e-notation and the plain SI unit are used.
254      * @param smallestPower int; the smallest exponent value that will be written using an SI prefix
255      * @param biggestPower int; the largest exponent value that will be written using an SI prefix
256      * @return String; formatted value of this DoubleScalar
257      */
258     public String toStringSIPrefixed(final int smallestPower, final int biggestPower)
259     {
260         // Override this method for weights, nonlinear units and DimensionLess.
261         if (!Double.isFinite(this.si))
262         {
263             return toString(getDisplayUnit().getStandardUnit());
264         }
265         // PK: I can't think of an easier way to figure out what the exponent will be; rounding of the mantissa to the available
266         // width makes this hard; This feels like an expensive way.
267         String check = String.format(this.si >= 0 ? "%10.8E" : "%10.7E", this.si);
268         int exponent = Integer.parseInt(check.substring(check.indexOf("E") + 1));
269         if (exponent < -24 || exponent < smallestPower || exponent > 24 + 2 || exponent > biggestPower)
270         {
271             // Out of SI prefix range; do not scale.
272             return String.format(this.si >= 0 ? "%10.4E" : "%10.3E", this.si) + " "
273                     + getDisplayUnit().getStandardUnit().getId();
274         }
275         Integer roundedExponent = (int) Math.ceil((exponent - 2.0) / 3) * 3;
276         // System.out.print(String.format("exponent=%d; roundedExponent=%d ", exponent, roundedExponent));
277         String key =
278                 SIPrefixes.FACTORS.get(roundedExponent).getDefaultTextualPrefix() + getDisplayUnit().getStandardUnit().getId();
279         U displayUnit = getDisplayUnit().getQuantity().getUnitByAbbreviation(key);
280         return toString(displayUnit);
281     }
282 
283     /** {@inheritDoc} */
284     @Override
285     public String toTextualString()
286     {
287         return toTextualString(getDisplayUnit());
288     }
289 
290     /** {@inheritDoc} */
291     @Override
292     public String toTextualString(final U displayUnit)
293     {
294         double d = ValueUtil.expressAsUnit(getSI(), displayUnit);
295         return format(d) + " " + displayUnit.getLocalizedTextualAbbreviation();
296     }
297 
298     /** {@inheritDoc} */
299     @Override
300     public String toDisplayString()
301     {
302         return toDisplayString(getDisplayUnit());
303     }
304 
305     /** {@inheritDoc} */
306     @Override
307     public String toDisplayString(final U displayUnit)
308     {
309         double d = ValueUtil.expressAsUnit(getSI(), displayUnit);
310         return format(d) + " " + displayUnit.getLocalizedDisplayAbbreviation();
311     }
312 
313     /** {@inheritDoc} */
314     @Override
315     @SuppressWarnings("checkstyle:designforextension")
316     public int hashCode()
317     {
318         final int prime = 31;
319         int result = getDisplayUnit().getStandardUnit().hashCode();
320         long temp;
321         temp = Double.doubleToLongBits(this.getSI());
322         result = prime * result + (int) (temp ^ (temp >>> 32));
323         return result;
324     }
325 
326     /** {@inheritDoc} */
327     @Override
328     @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces", "unchecked"})
329     public boolean equals(final Object obj)
330     {
331         if (this == obj)
332             return true;
333         if (obj == null)
334             return false;
335         if (getClass() != obj.getClass())
336             return false;
337         DoubleScalar<U, S> other = (DoubleScalar<U, S>) obj;
338         if (!getDisplayUnit().getStandardUnit().equals(other.getDisplayUnit().getStandardUnit()))
339             return false;
340         if (Double.doubleToLongBits(this.getSI()) != Double.doubleToLongBits(other.getSI()))
341             return false;
342         return true;
343     }
344 
345     /**********************************************************************************/
346     /********************************* STATIC METHODS *********************************/
347     /**********************************************************************************/
348 
349     /** The cache to make the lookup of the constructor for a Scalar belonging to a unit faster. */
350     private static final Map<Unit<?>, Constructor<? extends DoubleScalar<?, ?>>> CACHE = new HashMap<>();
351     
352     /**
353      * Instantiate the DoubleScalar based on its unit. Rigid check on types by the compiler.
354      * @param value double; the value
355      * @param unit U; the unit in which the value is expressed
356      * @return S; an instantiated DoubleScalar with the value expressed in the unit
357      * @param <U> the unit
358      * @param <S> the return type
359      */
360     public static <U extends Unit<U>, S extends DoubleScalar<U, S>> S instantiate(final double value, final U unit)
361     {
362         return instantiateAnonymous(value, unit);
363     }
364 
365     /**
366      * Instantiate the DoubleScalar with an SI value and add the displayUnit later. Rigid check on types by the compiler.
367      * @param valueSI double; the SIvalue
368      * @param displayUnit U; the unit in which the value will be displayed
369      * @return S; an instantiated DoubleScalar with the SI value and the display unit
370      * @param <U> the unit
371      * @param <S> the return type
372      */
373     public static <U extends Unit<U>, S extends DoubleScalar<U, S>> S instantiateSI(final double valueSI,
374             final U displayUnit)
375     {
376         S result = instantiateAnonymous(valueSI, displayUnit.getStandardUnit());
377         result.setDisplayUnit(displayUnit);
378         return result;
379     }
380 
381     /**
382      * Instantiate the DoubleScalar based on its unit. Loose check for types on the compiler. This allows the unit to be
383      * specified as a Unit&lt;?&gt; type.<br>
384      * <b>Note</b> that it is possible to make mistakes with anonymous units.
385      * @param value double; the value
386      * @param unit Unit&lt;?&gt;; the unit in which the value is expressed
387      * @return S; an instantiated DoubleScalar with the value expressed in the unit
388      * @param <S> the return type
389      */
390     @SuppressWarnings("unchecked")
391     public static <S extends DoubleScalar<?, S>> S instantiateAnonymous(final double value, final Unit<?> unit)
392     {
393         try
394         {
395             Constructor<? extends DoubleScalar<?, ?>> scalarConstructor = CACHE.get(unit);
396             if (scalarConstructor == null)
397             {
398                 if (!unit.getClass().getSimpleName().endsWith("Unit"))
399                 {
400                     throw new ClassNotFoundException("Unit " + unit.getClass().getSimpleName()
401                             + " name does noet end with 'Unit'. Cannot find corresponding scalar");
402                 }
403                 Class<? extends DoubleScalar<?, ?>> scalarClass;
404                 if (unit instanceof SIUnit)
405                 {
406                     scalarClass = SIScalar.class;
407                 }
408                 else
409                 {
410                     scalarClass = (Class<DoubleScalar<?, ?>>) Class
411                             .forName("org.djunits.value.vdouble.scalar." + unit.getClass().getSimpleName().replace("Unit", ""));
412                 }
413                 scalarConstructor = scalarClass.getDeclaredConstructor(double.class, unit.getClass());
414                 CACHE.put(unit, scalarConstructor);
415             }
416             return (S) scalarConstructor.newInstance(value, unit);
417         }
418         catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
419                 | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception)
420         {
421             throw new UnitRuntimeException("Cannot instantiate DoubleScalar of unit " + unit.toString() + ". Reason: "
422                     + exception.getMessage());
423         }
424     }
425 
426     /**
427      * Add a Relative value to an Absolute value. Return a new instance of the value. The unit of the return value will be the
428      * unit of the left argument.
429      * @param left A, an absolute typed DoubleScalar; the left argument
430      * @param right R, a relative typed DoubleScalar; the right argument
431      * @param <AU> Unit; the absolute unit of the parameters and the result
432      * @param <RU> Unit; the relative unit of the parameters and the result
433      * @param <R> the relative type
434      * @param <A> the corresponding absolute type
435      * @return A; an absolute typed DoubleScalar; the sum of the values as an Absolute value
436      */
437     public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
438             R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
439             A extends DoubleScalarAbs<AU, A, RU, R>> A plus(final A left, final R right)
440     {
441         return left.plus(right);
442     }
443 
444     /**
445      * Add an Absolute value to a Relative value. Return a new instance of the value. The unit of the return value will be the
446      * unit of the left argument.
447      * @param left A, an absolute typed DoubleScalar; the left argument
448      * @param right R, a relative typed DoubleScalar; the right argument
449      * @param <AU> Unit; the absolute unit of the parameters and the result
450      * @param <RU> Unit; the relative unit of the parameters and the result
451      * @param <R> the relative type
452      * @param <A> the corresponding absolute type
453      * @return A; an absolute typed DoubleScalar; the sum of the values as an Absolute value
454      */
455     public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
456             R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
457             A extends DoubleScalarAbs<AU, A, RU, R>> A plus(final R left, final A right)
458     {
459         return right.plus(left);
460     }
461 
462     /**
463      * Add a Relative value to a Relative value. Return a new instance of the value. The unit of the return value will be the
464      * unit of the left argument.
465      * @param left R, a relative typed DoubleScalar; the left argument
466      * @param right R, a relative typed DoubleScalar; the right argument
467      * @param <U> Unit; the unit of the parameters and the result
468      * @param <R> the relative type
469      * @return R; a relative typed DoubleScalar; the sum of the values as a Relative value
470      */
471     public static <U extends Unit<U>, R extends DoubleScalarRel<U, R>> R plus(final R left, final R right)
472     {
473         return left.plus(right);
474     }
475 
476     /**
477      * Subtract a Relative value from an absolute value. Return a new instance of the value. The unit of the return value will
478      * be the unit of the left argument.
479      * @param left A, an absolute typed DoubleScalar; the left value
480      * @param right R, a relative typed DoubleScalar; the right value
481      * @param <AU> Unit; the absolute unit of the parameters and the result
482      * @param <RU> Unit; the relative unit of the parameters and the result
483      * @param <R> the relative type
484      * @param <A> the corresponding absolute type
485      * @return A; an absolute typed DoubleScalar; the resulting value as an absolute value
486      */
487     public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
488             R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
489             A extends DoubleScalarAbs<AU, A, RU, R>> A minus(final A left, final R right)
490     {
491         return left.minus(right);
492     }
493 
494     /**
495      * Subtract a relative value from a relative value. Return a new instance of the value. The unit of the value will be the
496      * unit of the first argument.
497      * @param left R, a relative typed DoubleScalar; the left value
498      * @param right R, a relative typed DoubleScalar; the right value
499      * @param <U> Unit; the unit of the parameters and the result
500      * @param <R> the relative type
501      * @return R; a relative typed DoubleScalar; the resulting value as a relative value
502      */
503     public static <U extends Unit<U>, R extends DoubleScalarRel<U, R>> R minus(final R left, final R right)
504     {
505         return left.minus(right);
506     }
507 
508     /**
509      * Subtract two absolute values. Return a new instance of a relative value of the difference. The unit of the value will be
510      * the unit of the first argument.
511      * @param left A, an absolute typed DoubleScalar; value 1
512      * @param right A, an absolute typed DoubleScalar; value 2
513      * @param <AU> Unit; the absolute unit of the parameters and the result
514      * @param <RU> Unit; the relative unit of the parameters and the result
515      * @param <R> the relative type
516      * @param <A> the corresponding absolute type
517      * @return R; a relative typed DoubleScalar; the difference of the two absolute values as a relative value
518      */
519     public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
520             R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
521             A extends DoubleScalarAbs<AU, A, RU, R>> R minus(final A left, final A right)
522     {
523         return left.minus(right);
524     }
525 
526     /**
527      * Multiply two values; the result is a new instance with a different (existing or generated) SI unit.
528      * @param left DoubleScalarRel&lt;?, ?&gt;; the left operand
529      * @param right DoubleScalarRel&lt;?, ?&gt;; the right operand
530      * @return DoubleScalarRel&lt;SIUnit&gt;; the product of the two values
531      */
532     public static SIScalar multiply(final DoubleScalarRel<?, ?> left, final DoubleScalarRel<?, ?> right)
533     {
534         SIUnit targetUnit = Unit.lookupOrCreateUnitWithSIDimensions(left.getDisplayUnit().getQuantity().getSiDimensions()
535                 .plus(right.getDisplayUnit().getQuantity().getSiDimensions()));
536         return new SIScalar(left.getSI() * right.getSI(), targetUnit);
537     }
538 
539     /**
540      * Divide two values; the result is a new instance with a different (existing or generated) SI unit.
541      * @param left DoubleScalarRel&lt;?, ?&gt;; the left operand
542      * @param right DoubleScalarRel&lt;?, ?&gt;; the right operand
543      * @return DoubleScalarRel&lt;SIUnit&gt;; the ratio of the two values
544      */
545     public static SIScalar divide(final DoubleScalarRel<?, ?> left, final DoubleScalarRel<?, ?> right)
546     {
547         SIUnit targetUnit = Unit.lookupOrCreateUnitWithSIDimensions(left.getDisplayUnit().getQuantity().getSiDimensions()
548                 .minus(right.getDisplayUnit().getQuantity().getSiDimensions()));
549         return new SIScalar(left.getSI() / right.getSI(), targetUnit);
550     }
551 
552     /**
553      * Interpolate between two values. Made to be able to call e.g., Area a = DoubleScalar.interpolate(a1, a2, 0.4);
554      * @param zero R; the low value
555      * @param one R; the high value
556      * @param ratio double; the ratio between 0 and 1, inclusive
557      * @param <U> Unit; the unit of the parameters and the result
558      * @param <R> the relative type
559      * @return R; an Absolute Scalar at the <code>ratio</code> between <code>zero</code> and <code>one</code>
560      */
561     public static <U extends Unit<U>, R extends DoubleScalarRel<U, R>> R interpolate(final R zero, final R one,
562             final double ratio)
563     {
564         return zero.instantiateRel(zero.getInUnit() * (1 - ratio) + one.getInUnit(zero.getDisplayUnit()) * ratio,
565                 zero.getDisplayUnit());
566     }
567 
568     /**
569      * Interpolate between two values. Made to be able to call e.g., Time t = DoubleScalar.interpolate(t1, t2, 0.4);
570      * @param zero A; the low value
571      * @param one A; the high value
572      * @param ratio double; the ratio between 0 and 1, inclusive
573      * @param <AU> Unit; the absolute unit of the parameters and the result
574      * @param <RU> Unit; the relative unit of the parameters and the result
575      * @param <R> the relative type
576      * @param <A> the corresponding absolute type
577      * @return R; a Relative Scalar at the <code>ratio</code> between <code>zero</code> and <code>one</code>
578      */
579     public static <AU extends AbsoluteLinearUnit<AU, RU>, RU extends Unit<RU>,
580             R extends DoubleScalarRelWithAbs<AU, A, RU, R>,
581             A extends DoubleScalarAbs<AU, A, RU, R>> A interpolate(final A zero, final A one, final double ratio)
582     {
583         return zero.instantiateAbs(zero.getInUnit() * (1 - ratio) + one.getInUnit(zero.getDisplayUnit()) * ratio,
584                 zero.getDisplayUnit());
585     }
586 
587     /**
588      * Return the maximum value of two relative scalars.
589      * @param r1 T; the first scalar
590      * @param r2 T; the second scalar
591      * @param <U> Unit; the unit of the parameters and the result
592      * @param <T> the argument and result type
593      * @return T; the maximum value of two relative scalars
594      */
595     public static <U extends Unit<U>, T extends DoubleScalar<U, T>> T max(final T r1, final T r2)
596     {
597         return (r1.gt(r2)) ? r1 : r2;
598     }
599 
600     /**
601      * Return the maximum value of more than two relative scalars.
602      * @param r1 T; the first scalar
603      * @param r2 T; the second scalar
604      * @param rn T...; the other scalars
605      * @param <U> Unit; the unit of the parameters and the result
606      * @param <T> the argument and result type
607      * @return T; the maximum value of more than two relative scalars
608      */
609     @SafeVarargs
610     public static <U extends Unit<U>, T extends DoubleScalar<U, T>> T max(final T r1, final T r2, final T... rn)
611     {
612         T maxr = (r1.gt(r2)) ? r1 : r2;
613         for (T r : rn)
614         {
615             if (r.gt(maxr))
616             {
617                 maxr = r;
618             }
619         }
620         return maxr;
621     }
622 
623     /**
624      * Return the minimum value of two relative scalars.
625      * @param r1 T; the first scalar
626      * @param r2 T; the second scalar
627      * @param <U> Unit; the unit of the parameters and the result
628      * @param <T> the argument and result type
629      * @return T; the minimum value of two relative scalars
630      */
631     public static <U extends Unit<U>, T extends DoubleScalar<U, T>> T min(final T r1, final T r2)
632     {
633         return r1.lt(r2) ? r1 : r2;
634     }
635 
636     /**
637      * Return the minimum value of more than two relative scalars.
638      * @param r1 T; the first scalar
639      * @param r2 T; the second scalar
640      * @param rn T...; the other scalars
641      * @param <U> Unit; the unit of the parameters and the result
642      * @param <T> the argument and result type
643      * @return T; the minimum value of more than two relative scalars
644      */
645     @SafeVarargs
646     public static <U extends Unit<U>, T extends DoubleScalar<U, T>> T min(final T r1, final T r2, final T... rn)
647     {
648         T minr = r1.lt(r2) ? r1 : r2;
649         for (T r : rn)
650         {
651             if (r.lt(minr))
652             {
653                 minr = r;
654             }
655         }
656         return minr;
657     }
658 
659 }