@@ -20,26 +20,6 @@ pub struct LeastSquaresRef<'work, A: Scalar> {
20
20
pub rank : i32 ,
21
21
}
22
22
23
- #[ cfg_attr( doc, katexit:: katexit) ]
24
- /// Solve least square problem
25
- pub trait LeastSquaresSvdDivideConquer_ : Scalar {
26
- /// Compute a vector $x$ which minimizes Euclidian norm $\| Ax - b\|$
27
- /// for a given matrix $A$ and a vector $b$.
28
- fn least_squares (
29
- a_layout : MatrixLayout ,
30
- a : & mut [ Self ] ,
31
- b : & mut [ Self ] ,
32
- ) -> Result < LeastSquaresOwned < Self > > ;
33
-
34
- /// Solve least square problems $\argmin_X \| AX - B\|$
35
- fn least_squares_nrhs (
36
- a_layout : MatrixLayout ,
37
- a : & mut [ Self ] ,
38
- b_layout : MatrixLayout ,
39
- b : & mut [ Self ] ,
40
- ) -> Result < LeastSquaresOwned < Self > > ;
41
- }
42
-
43
23
pub struct LeastSquaresWork < T : Scalar > {
44
24
pub a_layout : MatrixLayout ,
45
25
pub b_layout : MatrixLayout ,
@@ -356,145 +336,3 @@ macro_rules! impl_least_squares_work_r {
356
336
}
357
337
impl_least_squares_work_r ! ( f64 , lapack_sys:: dgelsd_) ;
358
338
impl_least_squares_work_r ! ( f32 , lapack_sys:: sgelsd_) ;
359
-
360
- macro_rules! impl_least_squares {
361
- ( @real, $scalar: ty, $gelsd: path) => {
362
- impl_least_squares!( @body, $scalar, $gelsd, ) ;
363
- } ;
364
- ( @complex, $scalar: ty, $gelsd: path) => {
365
- impl_least_squares!( @body, $scalar, $gelsd, rwork) ;
366
- } ;
367
-
368
- ( @body, $scalar: ty, $gelsd: path, $( $rwork: ident) ,* ) => {
369
- impl LeastSquaresSvdDivideConquer_ for $scalar {
370
- fn least_squares(
371
- l: MatrixLayout ,
372
- a: & mut [ Self ] ,
373
- b: & mut [ Self ] ,
374
- ) -> Result <LeastSquaresOwned <Self >> {
375
- let b_layout = l. resized( b. len( ) as i32 , 1 ) ;
376
- Self :: least_squares_nrhs( l, a, b_layout, b)
377
- }
378
-
379
- fn least_squares_nrhs(
380
- a_layout: MatrixLayout ,
381
- a: & mut [ Self ] ,
382
- b_layout: MatrixLayout ,
383
- b: & mut [ Self ] ,
384
- ) -> Result <LeastSquaresOwned <Self >> {
385
- // Minimize |b - Ax|_2
386
- //
387
- // where
388
- // A : (m, n)
389
- // b : (max(m, n), nrhs) // `b` has to store `x` on exit
390
- // x : (n, nrhs)
391
- let ( m, n) = a_layout. size( ) ;
392
- let ( m_, nrhs) = b_layout. size( ) ;
393
- let k = m. min( n) ;
394
- assert!( m_ >= m) ;
395
-
396
- // Transpose if a is C-continuous
397
- let mut a_t = None ;
398
- let a_layout = match a_layout {
399
- MatrixLayout :: C { .. } => {
400
- let ( layout, t) = transpose( a_layout, a) ;
401
- a_t = Some ( t) ;
402
- layout
403
- }
404
- MatrixLayout :: F { .. } => a_layout,
405
- } ;
406
-
407
- // Transpose if b is C-continuous
408
- let mut b_t = None ;
409
- let b_layout = match b_layout {
410
- MatrixLayout :: C { .. } => {
411
- let ( layout, t) = transpose( b_layout, b) ;
412
- b_t = Some ( t) ;
413
- layout
414
- }
415
- MatrixLayout :: F { .. } => b_layout,
416
- } ;
417
-
418
- let rcond: Self :: Real = -1. ;
419
- let mut singular_values: Vec <MaybeUninit <Self :: Real >> = vec_uninit( k as usize ) ;
420
- let mut rank: i32 = 0 ;
421
-
422
- // eval work size
423
- let mut info = 0 ;
424
- let mut work_size = [ Self :: zero( ) ] ;
425
- let mut iwork_size = [ 0 ] ;
426
- $(
427
- let mut $rwork = [ Self :: Real :: zero( ) ] ;
428
- ) *
429
- unsafe {
430
- $gelsd(
431
- & m,
432
- & n,
433
- & nrhs,
434
- AsPtr :: as_mut_ptr( a_t. as_mut( ) . map( |v| v. as_mut_slice( ) ) . unwrap_or( a) ) ,
435
- & a_layout. lda( ) ,
436
- AsPtr :: as_mut_ptr( b_t. as_mut( ) . map( |v| v. as_mut_slice( ) ) . unwrap_or( b) ) ,
437
- & b_layout. lda( ) ,
438
- AsPtr :: as_mut_ptr( & mut singular_values) ,
439
- & rcond,
440
- & mut rank,
441
- AsPtr :: as_mut_ptr( & mut work_size) ,
442
- & ( -1 ) ,
443
- $( AsPtr :: as_mut_ptr( & mut $rwork) , ) *
444
- iwork_size. as_mut_ptr( ) ,
445
- & mut info,
446
- )
447
- } ;
448
- info. as_lapack_result( ) ?;
449
-
450
- // calc
451
- let lwork = work_size[ 0 ] . to_usize( ) . unwrap( ) ;
452
- let mut work: Vec <MaybeUninit <Self >> = vec_uninit( lwork) ;
453
- let liwork = iwork_size[ 0 ] . to_usize( ) . unwrap( ) ;
454
- let mut iwork: Vec <MaybeUninit <i32 >> = vec_uninit( liwork) ;
455
- $(
456
- let lrwork = $rwork[ 0 ] . to_usize( ) . unwrap( ) ;
457
- let mut $rwork: Vec <MaybeUninit <Self :: Real >> = vec_uninit( lrwork) ;
458
- ) *
459
- unsafe {
460
- $gelsd(
461
- & m,
462
- & n,
463
- & nrhs,
464
- AsPtr :: as_mut_ptr( a_t. as_mut( ) . map( |v| v. as_mut_slice( ) ) . unwrap_or( a) ) ,
465
- & a_layout. lda( ) ,
466
- AsPtr :: as_mut_ptr( b_t. as_mut( ) . map( |v| v. as_mut_slice( ) ) . unwrap_or( b) ) ,
467
- & b_layout. lda( ) ,
468
- AsPtr :: as_mut_ptr( & mut singular_values) ,
469
- & rcond,
470
- & mut rank,
471
- AsPtr :: as_mut_ptr( & mut work) ,
472
- & ( lwork as i32 ) ,
473
- $( AsPtr :: as_mut_ptr( & mut $rwork) , ) *
474
- AsPtr :: as_mut_ptr( & mut iwork) ,
475
- & mut info,
476
- ) ;
477
- }
478
- info. as_lapack_result( ) ?;
479
-
480
- let singular_values = unsafe { singular_values. assume_init( ) } ;
481
-
482
- // Skip a_t -> a transpose because A has been destroyed
483
- // Re-transpose b
484
- if let Some ( b_t) = b_t {
485
- transpose_over( b_layout, & b_t, b) ;
486
- }
487
-
488
- Ok ( LeastSquaresOwned {
489
- singular_values,
490
- rank,
491
- } )
492
- }
493
- }
494
- } ;
495
- }
496
-
497
- impl_least_squares ! ( @real, f64 , lapack_sys:: dgelsd_) ;
498
- impl_least_squares ! ( @real, f32 , lapack_sys:: sgelsd_) ;
499
- impl_least_squares ! ( @complex, c64, lapack_sys:: zgelsd_) ;
500
- impl_least_squares ! ( @complex, c32, lapack_sys:: cgelsd_) ;
0 commit comments