@@ -50,6 +50,17 @@ fn h2_norm<U: Time + 'static>(
5050 let m = b. ncols ( ) ;
5151 let p = c. nrows ( ) ;
5252
53+ assert ! ( m > 0 ) ;
54+ assert ! ( p > 0 ) ;
55+
56+ if n == 0 {
57+ let d_all_zero = d. iter ( ) . all ( |& x| x == 0.0 ) ;
58+ if d_all_zero {
59+ return Ok ( 0. ) ;
60+ }
61+ return Err ( "Order of system is zero and D matrix is not zero" . into ( ) ) ;
62+ }
63+
5364 let lda = a. nrows ( ) ;
5465 let ldb = b. nrows ( ) ;
5566 let ldc = c. nrows ( ) ;
@@ -66,6 +77,7 @@ fn h2_norm<U: Time + 'static>(
6677 let mut iwarn = -1 as c_int ;
6778 let mut info = -1 as c_int ;
6879
80+ // println!("lda: {}", lda);
6981 let h2_norm = unsafe {
7082 ab13bd_ (
7183 time_domain. as_ptr ( ) ,
@@ -92,13 +104,11 @@ fn h2_norm<U: Time + 'static>(
92104
93105 if info != 0 {
94106 return Err ( Box :: new ( std:: io:: Error :: other ( format ! (
95- "SLICOT ab13bd failed with the follwing error indicator: {}" ,
96- info
107+ "SLICOT ab13bd failed with the follwing error indicator: {info}"
97108 ) ) ) ) ;
98109 } else if iwarn != 0 {
99110 return Err ( Box :: new ( std:: io:: Error :: other ( format ! (
100- "SLICOT ab13bd returned with warning about numerical stability. Iwarn = {}" ,
101- iwarn
111+ "SLICOT ab13bd returned with warning about numerical stability. Iwarn = {iwarn}"
102112 ) ) ) ) ;
103113 }
104114
@@ -122,6 +132,21 @@ fn hinf_norm<U: Time + 'static>(
122132) -> Result < f64 , String > {
123133 Ss :: < U > :: verify_dimensions ( & a, & b, & c, & d) . map_err ( |e| e. to_string ( ) ) ?;
124134
135+ let n = a. nrows ( ) ;
136+ let m = b. ncols ( ) ;
137+ let p = c. nrows ( ) ;
138+
139+ assert ! ( p > 0 ) ;
140+ assert ! ( m > 0 ) ;
141+
142+ if n == 0 {
143+ // The gain is constant and equal to D
144+ // H-inf norm is the largest singular value
145+ let singular_values = d. singular_values ( ) ;
146+ let max_singular_value = singular_values. max ( ) ;
147+ return Ok ( max_singular_value) ;
148+ }
149+
125150 let time_domain = if std:: any:: TypeId :: of :: < U > ( )
126151 == std:: any:: TypeId :: of :: < Continuous > ( )
127152 {
@@ -137,10 +162,6 @@ fn hinf_norm<U: Time + 'static>(
137162 let equilibration = CString :: new ( "S" ) . unwrap ( ) ; // Perform scaling
138163 let d_is_nonzero = CString :: new ( "D" ) . unwrap ( ) ;
139164
140- let n = a. nrows ( ) ;
141- let m = b. ncols ( ) ;
142- let p = c. nrows ( ) ;
143-
144165 let mut e = DMatrix :: identity ( n, n) ;
145166
146167 let mut f_peak = [ 0.0 , 1.0 ] ; // initial guess not active
@@ -199,8 +220,7 @@ fn hinf_norm<U: Time + 'static>(
199220
200221 if info != 0 {
201222 return Err ( format ! (
202- "SLICOT ab13dd returned with error code. info = {}" ,
203- info
223+ "SLICOT ab13dd returned with error code. info = {info}"
204224 ) ) ;
205225 }
206226
@@ -293,8 +313,7 @@ pub fn zeros(
293313
294314 if info != 0 {
295315 return Err ( format ! (
296- "SLICOT failed to find zeros of state-space system. Info = {}" ,
297- info
316+ "SLICOT failed to find zeros of state-space system. Info = {info}"
298317 ) ) ;
299318 }
300319 let ldwork = dwork[ 0 ] as usize ;
@@ -336,8 +355,7 @@ pub fn zeros(
336355
337356 if info != 0 {
338357 return Err ( format ! (
339- "SLICOT failed to find zeros of state-space system. Info = {}" ,
340- info
358+ "SLICOT failed to find zeros of state-space system. Info = {info}"
341359 ) ) ;
342360 }
343361 if num_inv_zeros == 0 {
@@ -384,7 +402,7 @@ pub fn zeros(
384402 ) ;
385403 }
386404 if info != 0 {
387- return Err ( format ! ( "LAPACK DGGEV returned info = {}" , info ) ) ;
405+ return Err ( format ! ( "LAPACK DGGEV returned info = {info}" ) ) ;
388406 }
389407 lwork = dwork[ 0 ] as c_int ;
390408 assert ! ( lwork > 0 ) ;
@@ -413,7 +431,7 @@ pub fn zeros(
413431 ) ;
414432 }
415433 if info != 0 {
416- return Err ( format ! ( "LAPACK DGGEV returned info = {}" , info ) ) ;
434+ return Err ( format ! ( "LAPACK DGGEV returned info = {info}" ) ) ;
417435 }
418436
419437 let mut zeros = Vec :: with_capacity ( n_gen_eigen) ;
@@ -446,6 +464,7 @@ impl<U: Time + 'static> Ss<U> {
446464 /// - `Ok(f64)`: The H2 norm of the system.
447465 /// - `Err(String)`: An error message if the computation fails.
448466 pub fn norm_h2 ( & self ) -> Result < f64 , String > {
467+ // println!("before h2: {}", self);
449468 h2_norm :: < U > (
450469 self . a ( ) . clone ( ) ,
451470 self . b ( ) . clone ( ) ,
@@ -510,6 +529,7 @@ impl<U: Time + 'static> Ss<U> {
510529#[ cfg( test) ]
511530mod tests {
512531 use crate :: {
532+ Continuous , Ss ,
513533 systems:: Tf ,
514534 transformations:: SsRealization :: { ControllableCF , ObservableCF } ,
515535 } ;
@@ -546,6 +566,13 @@ mod tests {
546566 epsilon = 1e-2
547567 ) ;
548568 }
569+
570+ let sys = Ss :: < Continuous > :: new_from_scalar ( -2.0 ) ;
571+ assert_abs_diff_eq ! ( sys. norm_hinf( ) . unwrap( ) , 2.0 ) ;
572+
573+ assert ! ( sys. norm_h2( ) . is_err( ) ) ;
574+ let sys = Ss :: < Continuous > :: new_from_scalar ( 0.0 ) ;
575+ assert_eq ! ( sys. norm_h2( ) . unwrap( ) , 0.0 ) ;
549576 }
550577
551578 #[ test]
@@ -592,9 +619,9 @@ mod tests {
592619 #[ test]
593620 fn ss_zeros ( ) {
594621 let tf = ( Tf :: s ( ) - 1.0 ) * ( Tf :: s ( ) + 4.0 ) / ( Tf :: s ( ) + 2.0 ) . powi ( 2 ) ;
595- println ! ( "tf: \n {}" , tf ) ;
622+ println ! ( "tf: \n {tf}" ) ;
596623 let zeros = tf. to_ss_method ( ControllableCF ) . unwrap ( ) . zeros ( ) . unwrap ( ) ;
597- println ! ( "zeros: {:?}" , zeros ) ;
624+ println ! ( "zeros: {zeros :?}" ) ;
598625 assert_eq ! ( zeros. len( ) , 2 ) ;
599626
600627 let tf = 1.0 / Tf :: s ( ) ;
@@ -643,18 +670,18 @@ mod tests {
643670 #[ test]
644671 fn ss_is_stable ( ) {
645672 let tf = 1.0 / Tf :: s ( ) ;
646- assert_eq ! ( tf. to_ss_method( ObservableCF ) . unwrap( ) . is_stable( ) , false ) ;
673+ assert ! ( ! tf. to_ss_method( ObservableCF ) . unwrap( ) . is_stable( ) ) ;
647674
648675 let tf = ( Tf :: s ( ) + 1.0 ) / ( Tf :: s ( ) + 1.0 ) . powi ( 4 ) ;
649676 let ss = tf. to_ss_method ( ObservableCF ) . unwrap ( ) ;
650- assert_eq ! ( ss. is_stable( ) , true ) ;
677+ assert ! ( ss. is_stable( ) ) ;
651678
652679 let tf = 1.0 / ( ( Tf :: s ( ) + 1.0 ) * ( Tf :: s ( ) - 2.0 ) ) ;
653680 let ss = tf. to_ss_method ( ObservableCF ) . unwrap ( ) ;
654- assert_eq ! ( ss. is_stable( ) , false ) ;
681+ assert ! ( ! ss. is_stable( ) ) ;
655682
656683 let tf = 1.0 / ( Tf :: s ( ) . powi ( 2 ) + 2.0 * 0.01 * Tf :: s ( ) + 1.0 ) ;
657684 let ss = tf. to_ss_method ( ObservableCF ) . unwrap ( ) ;
658- assert_eq ! ( ss. is_stable( ) , true ) ;
685+ assert ! ( ss. is_stable( ) ) ;
659686 }
660687}
0 commit comments