1   /* Copyright 2002-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.propagation.semianalytical.dsst.utilities.hansen;
18  
19  import org.hipparchus.analysis.polynomials.PolynomialFunction;
20  
21  /**
22   * Utilities class.
23   *
24   * @author Lucian Barbulescu
25   */
26  public class HansenUtilities {
27  
28      /** 1 represented as a polynomial. */
29      public static final PolynomialFunction ONE = new PolynomialFunction(new double[] {
30          1
31      });
32  
33      /** 0 represented as a polynomial. */
34      public static final PolynomialFunction ZERO = new PolynomialFunction(new double[] {
35          0
36      });
37  
38      /** Private constructor as class is a utility.
39       */
40      private HansenUtilities() {
41      }
42  
43      /**
44       * Build the identity matrix of order 2.
45       *
46       * <pre>
47       *       / 1   0 \
48       *  I₂ = |       |
49       *       \ 0   1 /
50       * </pre>
51       *
52       * @return the identity matrix of order 2
53       */
54      public static PolynomialFunctionMatrix buildIdentityMatrix2() {
55          final PolynomialFunctionMatrix matrix = new PolynomialFunctionMatrix(2);
56          matrix.setMatrix(new PolynomialFunction[][] {
57              {
58                  ONE,  ZERO
59              },
60              {
61                  ZERO, ONE
62              }
63          });
64          return matrix;
65      }
66  
67      /**
68       * Build the empty matrix of order 2.
69       *
70       * <pre>
71       *       / 0   0 \
72       *  E₂ = |       |
73       *       \ 0   0 /
74       * </pre>
75       *
76       * @return the identity matrix of order 2
77       */
78      public static PolynomialFunctionMatrix buildZeroMatrix2() {
79          final PolynomialFunctionMatrix matrix = new PolynomialFunctionMatrix(2);
80          matrix.setMatrix(new PolynomialFunction[][] {
81              {
82                  ZERO, ZERO
83              },
84              {
85                  ZERO, ZERO
86              }
87          });
88          return matrix;
89      }
90  
91  
92      /**
93       * Build the identity matrix of order 4.
94       *
95       * <pre>
96       *       / 1  0  0  0 \
97       *       |            |
98       *       | 0  1  0  0 |
99       *  I₄ = |            |
100      *       | 0  0  1  0 |
101      *       |            |
102      *       \ 0  0  0  1 /
103      * </pre>
104      *
105      * @return the identity matrix of order 4
106      */
107     public static PolynomialFunctionMatrix buildIdentityMatrix4() {
108         final PolynomialFunctionMatrix matrix = new PolynomialFunctionMatrix(4);
109         matrix.setMatrix(new PolynomialFunction[][] {
110             {
111                 ONE,  ZERO, ZERO, ZERO
112             },
113             {
114                 ZERO, ONE,  ZERO, ZERO
115             },
116             {
117                 ZERO, ZERO, ONE,  ZERO
118             },
119             {
120                 ZERO, ZERO, ZERO, ONE
121             }
122         });
123         return matrix;
124     }
125 
126     /**
127      * Build the empty matrix of order 4.
128      *
129      * <pre>
130      *       / 0  0  0  0 \
131      *       |            |
132      *       | 0  0  0  0 |
133      *  E₄ = |            |
134      *       | 0  0  0  0 |
135      *       |            |
136      *       \ 0  0  0  0 /
137      * </pre>
138      *
139      * @return the identity matrix of order 4
140      */
141     public static PolynomialFunctionMatrix buildZeroMatrix4() {
142         final PolynomialFunctionMatrix matrix = new PolynomialFunctionMatrix(4);
143         matrix.setMatrix(new PolynomialFunction[][] {
144             {
145                 ZERO, ZERO, ZERO, ZERO
146             },
147             {
148                 ZERO, ZERO, ZERO, ZERO
149             },
150             {
151                 ZERO, ZERO, ZERO, ZERO
152             },
153             {
154                 ZERO, ZERO, ZERO, ZERO
155             }
156         } );
157         return matrix;
158     }
159 
160     /**
161      * Compute polynomial coefficient a.
162      *
163      *  <p>
164      *  It is used to generate the coefficient for K₀<sup>-n, s</sup> when computing K₀<sup>-n-1, s</sup>
165      *  and the coefficient for dK₀<sup>-n, s</sup> / de² when computing dK₀<sup>-n-1, s</sup> / de²
166      *  </p>
167      *
168      *  <p>
169      *  See Danielson 2.7.3-(6) and Collins 4-242 and 4-245
170      *  </p>
171      *
172      * @param s the s coefficient
173      * @param mnm1 -n-1 value
174      * @return the polynomial
175      */
176     private static PolynomialFunction aZonal(final int s, final int mnm1) {
177         // from recurrence Collins 4-242
178         final double d1 = (mnm1 + 2) * (2 * mnm1 + 5);
179         final double d2 = (mnm1 + 2 - s) * (mnm1 + 2 + s);
180         return new PolynomialFunction(new double[] {
181             0.0, 0.0, d1 / d2
182         });
183     }
184 
185     /**
186      * Compute polynomial coefficient b.
187      *
188      *  <p>
189      *  It is used to generate the coefficient for K₀<sup>-n+1, s</sup> when computing K₀<sup>-n-1, s</sup>
190      *  and the coefficient for dK₀<sup>-n+1, s</sup> / de² when computing dK₀<sup>-n-1, s</sup> / de²
191      *  </p>
192      *
193      *  <p>
194      *  See Danielson 2.7.3-(6) and Collins 4-242 and 4-245
195      *  </p>
196      *
197      * @param s the s coefficient
198      * @param mnm1 -n-1 value
199      * @return the polynomial
200      */
201     private static PolynomialFunction bZonal(final int s, final int mnm1) {
202         // from recurence Collins 4-242
203         final double d1 = (mnm1 + 2) * (mnm1 + 3);
204         final double d2 = (mnm1 + 2 - s) * (mnm1 + 2 + s);
205         return new PolynomialFunction(new double[] {
206             0.0, 0.0, -d1 / d2
207         });
208     }
209 
210     /**
211      * Generate the polynomials needed in the linear transformation.
212      *
213      * @param n0         the index of the initial condition, Petre's paper
214      * @param nMin       rhe minimum value for the order
215      * @param offset     offset used to identify the polynomial that corresponds
216      *                   to a negative value of n in the internal array that
217      *                   starts at 0
218      * @param slice      number of coefficients that will be computed with a set
219      *                   of roots
220      * @param s          the s coefficient
221      * @param mpvec      array to store the first vector of polynomials
222      *                   associated to Hansen coefficients and derivatives.
223      * @param mpvecDeriv array to store the second vector of polynomials
224      *                   associated only to derivatives.
225      * <p>
226      * See Petre's paper
227      * </p>
228      */
229     public static void generateZonalPolynomials(final int n0, final int nMin,
230                                                 final int offset, final int slice,
231                                                 final int s,
232                                                 final PolynomialFunction[][] mpvec,
233                                                 final PolynomialFunction[][] mpvecDeriv) {
234 
235         int sliceCounter = 0;
236         int index;
237 
238         // Initialisation of matrix for linear transformmations
239         // The final configuration of these matrix are obtained by composition
240         // of linear transformations
241         PolynomialFunctionMatrix A = HansenUtilities.buildIdentityMatrix2();
242         PolynomialFunctionMatrix D = HansenUtilities.buildZeroMatrix2();
243         PolynomialFunctionMatrix E = HansenUtilities.buildIdentityMatrix2();
244 
245         // generation of polynomials associated to Hansen coefficients and to
246         // their derivatives
247         final PolynomialFunctionMatrix a = HansenUtilities.buildZeroMatrix2();
248         a.setElem(0, 1, HansenUtilities.ONE);
249 
250         //The B matrix is constant.
251         final PolynomialFunctionMatrix B = HansenUtilities.buildZeroMatrix2();
252         // from Collins 4-245 and Petre's paper
253         B.setElem(1, 1, new PolynomialFunction(new double[] {
254             2.0
255         }));
256 
257         for (int i = n0 - 1; i > nMin - 1; i--) {
258             index = i + offset;
259             // Matrix of the current linear transformation
260             // Petre's paper
261             a.setMatrixLine(1, new PolynomialFunction[] {
262                 bZonal(s, i), aZonal(s, i)
263             });
264             // composition of linear transformations
265             // see Petre's paper
266             A = A.multiply(a);
267             // store the polynomials for Hansen coefficients
268             mpvec[index] = A.getMatrixLine(1);
269 
270             D = D.multiply(a);
271             E = E.multiply(a);
272             D = D.add(E.multiply(B));
273 
274             // store the polynomials for Hansen coefficients from the expressions
275             // of derivatives
276             mpvecDeriv[index] = D.getMatrixLine(1);
277 
278             if (++sliceCounter % slice == 0) {
279                 // Re-Initialisation of matrix for linear transformmations
280                 // The final configuration of these matrix are obtained by composition
281                 // of linear transformations
282                 A = HansenUtilities.buildIdentityMatrix2();
283                 D = HansenUtilities.buildZeroMatrix2();
284                 E = HansenUtilities.buildIdentityMatrix2();
285             }
286 
287         }
288     }
289 
290     /**
291      * Compute polynomial coefficient a.
292      *
293      *  <p>
294      *  It is used to generate the coefficient for K<sub>j</sub><sup>-n, s</sup> when computing K<sub>j</sub><sup>-n-1, s</sup>
295      *  and the coefficient for dK<sub>j</sub><sup>-n, s</sup> / de² when computing dK<sub>j</sub><sup>-n-1, s</sup> / de²
296      *  </p>
297      *
298      *  <p>
299      *  See Danielson 2.7.3-(9) and Collins 4-236 and 4-240
300      *  </p>
301      *
302      * @param s the s coefficient
303      * @param mnm1 -n-1
304      * @return the polynomial
305      */
306     private static PolynomialFunction aTesseral(final int s, final int mnm1) {
307         // Collins 4-236, Danielson 2.7.3-(9)
308         final double r1 = (mnm1 + 2.) * (2. * mnm1 + 5.);
309         final double r2 = (2. + mnm1 + s) * (2. + mnm1 - s);
310         return new PolynomialFunction(new double[] {
311             0.0, 0.0, r1 / r2
312         });
313     }
314 
315     /**
316      * Compute polynomial coefficient b.
317      *
318      *  <p>
319      *  It is used to generate the coefficient for K<sub>j</sub><sup>-n+1, s</sup> when computing K<sub>j</sub><sup>-n-1, s</sup>
320      *  and the coefficient for dK<sub>j</sub><sup>-n+1, s</sup> / de² when computing dK<sub>j</sub><sup>-n-1, s</sup> / de²
321      *  </p>
322      *
323      *  <p>
324      *  See Danielson 2.7.3-(9) and Collins 4-236 and 4-240
325      *  </p>
326      *
327      * @param j the j coefficient
328      * @param s the s coefficient
329      * @param mnm1 -n-1
330      * @return the polynomial
331      */
332     private static PolynomialFunction bTesseral(final int j, final int s, final int mnm1) {
333         // Collins 4-236, Danielson 2.7.3-(9)
334         final double r2 = (2. + mnm1 + s) * (2. + mnm1 - s);
335         final double d1 = (mnm1 + 3.) * 2. * j * s / (r2 * (mnm1 + 4.));
336         final double d2 = (mnm1 + 3.) * (mnm1 + 2.) / r2;
337         return new PolynomialFunction(new double[] {
338             0.0, -d1, -d2
339         });
340     }
341 
342     /**
343      * Compute polynomial coefficient c.
344      *
345      *  <p>
346      *  It is used to generate the coefficient for K<sub>j</sub><sup>-n+3, s</sup> when computing K<sub>j</sub><sup>-n-1, s</sup>
347      *  and the coefficient for dK<sub>j</sub><sup>-n+3, s</sup> / de² when computing dK<sub>j</sub><sup>-n-1, s</sup> / de²
348      *  </p>
349      *
350      *  <p>
351      *  See Danielson 2.7.3-(9) and Collins 4-236 and 4-240
352      *  </p>
353      *
354      * @param j the j coefficient
355      * @param s the s coefficient
356      * @param mnm1 -n-1
357      * @return the polynomial
358      */
359     private static PolynomialFunction cTesseral(final int j, final int s, final int mnm1) {
360         // Collins 4-236, Danielson 2.7.3-(9)
361         final double r1 = j * j * (mnm1 + 2.);
362         final double r2 = (mnm1 + 4.) * (2. + mnm1 + s) * (2. + mnm1 - s);
363 
364         return new PolynomialFunction(new double[] {
365             0.0, 0.0, r1 / r2
366         });
367     }
368 
369     /**
370      * Compute polynomial coefficient d.
371      * <p>
372      * It is used to generate the coefficient for K<sub>j</sub><sup>-n-1,
373      * s</sup> / dχ when computing dK<sub>j</sub><sup>-n-1, s</sup> / de²
374      * </p>
375      * <p>
376      * See Danielson 2.7.3-(9) and Collins 4-236 and 4-240
377      * </p>
378      *
379      * @return the polynomial
380      */
381     private static PolynomialFunction dTesseral() {
382         // Collins 4-236, Danielson 2.7.3-(9)
383         return new PolynomialFunction(new double[] {
384             0.0, 0.0, 1.0
385         });
386     }
387 
388     /**
389      * Compute polynomial coefficient f.
390      *
391      *  <p>
392      *  It is used to generate the coefficient for K<sub>j</sub><sup>-n+1, s</sup> / dχ when computing dK<sub>j</sub><sup>-n-1, s</sup> / de²
393      *  </p>
394      *
395      *  <p>
396      *  See Danielson 2.7.3-(9) and Collins 4-236 and 4-240
397      *  </p>
398      *
399      * @param j the j coefficient
400      * @param s the s coefficient
401      * @param n index
402      * @return the polynomial
403      */
404     private static PolynomialFunction fTesseral(final int j, final int s, final int n) {
405         // Collins 4-236, Danielson 2.7.3-(9)
406         final double r1 = (n + 3.0) * j * s;
407         final double r2 = (n + 4.0) * (2.0 + n + s) * (2.0 + n - s);
408         return new PolynomialFunction(new double[] {
409             0.0, 0.0, 0.0, r1 / r2
410         });
411     }
412 
413     /**
414      * Generate the polynomials needed in the linear transformation.
415      *
416      * @param n0         the index of the initial condition, Petre's paper
417      * @param nMin       rhe minimum value for the order
418      * @param offset     offset used to identify the polynomial that corresponds
419      *                   to a negative value of n in the internal array that
420      *                   starts at 0
421      * @param slice      number of coefficients that will be computed with a set
422      *                   of roots
423      * @param j          the j coefficient
424      * @param s          the s coefficient
425      * @param mpvec      array to store the first vector of polynomials
426      *                   associated to Hansen coefficients and derivatives.
427      * @param mpvecDeriv array to store the second vector of polynomials
428      *                   associated only to derivatives.
429      */
430     public static void generateTesseralPolynomials(final int n0, final int nMin,
431                                                    final int offset, final int slice,
432                                                    final int j, final int s,
433                                                    final PolynomialFunction[][] mpvec,
434                                                    final PolynomialFunction[][] mpvecDeriv) {
435 
436 
437         // Initialization of the matrices for linear transformations
438         // The final configuration of these matrices are obtained by composition
439         // of linear transformations
440 
441         // The matrix of polynomials associated to Hansen coefficients, Petre's
442         // paper
443         PolynomialFunctionMatrix A = HansenUtilities.buildIdentityMatrix4();
444 
445         // The matrix of polynomials associated to derivatives, Petre's paper
446         final PolynomialFunctionMatrix B = HansenUtilities.buildZeroMatrix4();
447         PolynomialFunctionMatrix D = HansenUtilities.buildZeroMatrix4();
448         final PolynomialFunctionMatrix a = HansenUtilities.buildZeroMatrix4();
449 
450         // The matrix of the current linear transformation
451         a.setMatrixLine(0, new PolynomialFunction[] {
452             HansenUtilities.ZERO, HansenUtilities.ONE, HansenUtilities.ZERO, HansenUtilities.ZERO
453         });
454         a.setMatrixLine(1, new PolynomialFunction[] {
455             HansenUtilities.ZERO, HansenUtilities.ZERO, HansenUtilities.ONE, HansenUtilities.ZERO
456         });
457         a.setMatrixLine(2, new PolynomialFunction[] {
458             HansenUtilities.ZERO, HansenUtilities.ZERO, HansenUtilities.ZERO, HansenUtilities.ONE
459         });
460         // The generation process
461         int index;
462         int sliceCounter = 0;
463         for (int i = n0 - 1; i > nMin - 1; i--) {
464             index = i + offset;
465             // The matrix of the current linear transformation is updated
466             // Petre's paper
467             a.setMatrixLine(3, new PolynomialFunction[] {
468                 cTesseral(j, s, i), HansenUtilities.ZERO, bTesseral(j, s, i), aTesseral(s, i)
469             });
470 
471             // composition of the linear transformations to calculate
472             // the polynomials associated to Hansen coefficients
473             // Petre's paper
474             A = A.multiply(a);
475             // store the polynomials for Hansen coefficients
476             mpvec[index] = A.getMatrixLine(3);
477             // composition of the linear transformations to calculate
478             // the polynomials associated to derivatives
479             // Petre's paper
480             D = D.multiply(a);
481 
482             //Update the B matrix
483             B.setMatrixLine(3, new PolynomialFunction[] {
484                 HansenUtilities.ZERO, fTesseral(j, s, i),
485                 HansenUtilities.ZERO, dTesseral()
486             });
487             D = D.add(A.multiply(B));
488 
489             // store the polynomials for Hansen coefficients from the
490             // expressions of derivatives
491             mpvecDeriv[index] = D.getMatrixLine(3);
492 
493             if (++sliceCounter % slice == 0) {
494                 // Re-Initialisation of matrix for linear transformmations
495                 // The final configuration of these matrix are obtained by composition
496                 // of linear transformations
497                 A = HansenUtilities.buildIdentityMatrix4();
498                 D = HansenUtilities.buildZeroMatrix4();
499             }
500         }
501     }
502 
503     /**
504      * Compute polynomial coefficient a.
505      *
506      *  <p>
507      *  It is used to generate the coefficient for K₀<sup>n-1, s</sup> when computing K₀<sup>n, s</sup>
508      *  and the coefficient for dK₀<sup>n-1, s</sup> / d&Chi; when computing dK₀<sup>n, s</sup> / d&Chi;
509      *  </p>
510      *
511      *  <p>
512      *  See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
513      *  </p>
514      *
515      * @param n n value
516      * @return the polynomial
517      */
518     private static PolynomialFunction aThirdBody(final int n) {
519         // from recurrence Danielson 2.7.3-(7c), Collins 4-254
520         final double r1 = 2 * n + 1;
521         final double r2 = n + 1;
522 
523         return new PolynomialFunction(new double[] {
524             r1 / r2
525         });
526     }
527 
528     /**
529      * Compute polynomial coefficient b.
530      *
531      *  <p>
532      *  It is used to generate the coefficient for K₀<sup>n-2, s</sup> when computing K₀<sup>n, s</sup>
533      *  and the coefficient for dK₀<sup>n-2, s</sup> / d&Chi; when computing dK₀<sup>n, s</sup> / d&Chi;
534      *  </p>
535      *
536      *  <p>
537      *  See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
538      *  </p>
539      *
540      * @param s          the s coefficient
541      * @param n n value
542      * @return the polynomial
543      */
544     private static PolynomialFunction bThirdBody(final int s, final int n) {
545         // from recurrence Danielson 2.7.3-(7c), Collins 4-254
546         final double r1 = (n + s) * (n - s);
547         final double r2 = n * (n + 1);
548 
549         return new PolynomialFunction(new double[] {
550             0.0, 0.0, -r1 / r2
551         });
552     }
553 
554     /**
555      * Compute polynomial coefficient d.
556      *
557      *  <p>
558      *  It is used to generate the coefficient for K₀<sup>n-2, s</sup> when computing dK₀<sup>n, s</sup> / d&Chi;
559      *  </p>
560      *
561      *  <p>
562      *  See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
563      *  </p>
564      *
565      * @param s the s coefficient
566      * @param n n value
567      * @return the polynomial
568      */
569     private static PolynomialFunction dThirdBody(final int s, final int n) {
570         // from Danielson 3.2-(3b)
571         final double r1 = 2 * (n + s) * (n - s);
572         final double r2 = n * (n + 1);
573 
574         return new PolynomialFunction(new double[] {
575             0.0, 0.0, 0.0, r1 / r2
576         });
577     }
578 
579     /**
580      * Generate the polynomials needed in the linear transformation.
581      *
582      * @param n0 the index of the initial condition, Petre's paper
583      * @param nMax the maximum order of n indexes
584      * @param slice number of coefficients that will be computed with a set of roots
585      * @param s the s coefficient
586      * @param mpvec      array to store the first vector of polynomials
587      *                   associated to Hansen coefficients and derivatives.
588      * @param mpvecDeriv array to store the second vector of polynomials
589      *                   associated only to derivatives.
590      * <p>
591      * See Petre's paper
592      * </p>
593      */
594     public static void generateThirdBodyPolynomials(final int n0, final int nMax,
595                                                     final int slice,
596                                                     final int s,
597                                                     final PolynomialFunction[][] mpvec,
598                                                     final PolynomialFunction[][] mpvecDeriv) {
599 
600         int sliceCounter = 0;
601 
602         // Initialization of the matrices for linear transformations
603         // The final configuration of these matrices are obtained by composition
604         // of linear transformations
605 
606         // the matrix A for the polynomials associated
607         // to Hansen coefficients, Petre's pater
608         PolynomialFunctionMatrix A = HansenUtilities.buildIdentityMatrix2();
609 
610         // the matrix D for the polynomials associated
611         // to derivatives, Petre's paper
612         final PolynomialFunctionMatrix B = HansenUtilities.buildZeroMatrix2();
613         PolynomialFunctionMatrix D = HansenUtilities.buildZeroMatrix2();
614         PolynomialFunctionMatrix E = HansenUtilities.buildIdentityMatrix2();
615 
616         // The matrix that contains the coefficients at each step
617         final PolynomialFunctionMatrix a = HansenUtilities.buildZeroMatrix2();
618         a.setElem(0, 1, HansenUtilities.ONE);
619 
620         // The generation process
621         for (int i = n0 + 2; i <= nMax; i++) {
622             // Collins 4-254 or Danielson 2.7.3-(7)
623             // Petre's paper
624             // The matrix of the current linear transformation is actualized
625             a.setMatrixLine(1, new PolynomialFunction[] {
626                 bThirdBody(s, i), aThirdBody(i)
627             });
628 
629             // composition of the linear transformations to calculate
630             // the polynomials associated to Hansen coefficients
631             A = A.multiply(a);
632             // store the polynomials associated to Hansen coefficients
633             mpvec[i] = A.getMatrixLine(1);
634             // composition of the linear transformations to calculate
635             // the polynomials associated to derivatives
636             // Danielson 3.2-(3b) and Petre's paper
637             D = D.multiply(a);
638             if (sliceCounter % slice != 0) {
639                 a.setMatrixLine(1, new PolynomialFunction[] {
640                     bThirdBody(s, i - 1), aThirdBody(i - 1)
641                 });
642                 E = E.multiply(a);
643             }
644 
645             B.setElem(1, 0, dThirdBody(s, i));
646             // F = E.prod(B);
647             D = D.add(E.multiply(B));
648             // store the polynomials associated to the derivatives
649             mpvecDeriv[i] = D.getMatrixLine(1);
650 
651             if (++sliceCounter % slice == 0) {
652                 // Re-Initialization of the matrices for linear transformations
653                 // The final configuration of these matrices are obtained by composition
654                 // of linear transformations
655                 A = HansenUtilities.buildIdentityMatrix2();
656                 D = HansenUtilities.buildZeroMatrix2();
657                 E = HansenUtilities.buildIdentityMatrix2();
658             }
659         }
660     }
661 
662 }