RsBundle  Check-in [878867274d]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Move blas vector operations to `data::raw`
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | minorant-trait
Files: files | file ages | folders
SHA1: 878867274df02fc545b05db255b9f573ef8f1874
User & Date: fifr 2020-07-20 16:01:28.745
Context
2020-07-20
16:45
minorant: add function `combine_minorants` check-in: 73880f0fec user: fifr tags: minorant-trait
16:01
Move blas vector operations to `data::raw` check-in: 878867274d user: fifr tags: minorant-trait
15:33
minorant: remove `into_parts` check-in: dae1108c60 user: fifr tags: minorant-trait
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/data/minorant.rs.
15
16
17
18
19
20
21


22
23
24
25
26
27
28
//

//! A linear minorant.

use super::{Aggregatable, DVector, Real};
use num_traits::Zero;
use std::borrow::Borrow;



/// A linear minorant of a convex function.
///
/// A linear minorant of a convex function $f \colon \mathbb{R}\^n \to
/// \mathbb{R}$ is a linear function of the form
///
///   \\[ l \colon \mathbb{R}\^n \to \mathbb{R}, x \mapsto \langle g, x







>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//

//! A linear minorant.

use super::{Aggregatable, DVector, Real};
use num_traits::Zero;
use std::borrow::Borrow;

use crate::data::raw::BLAS1;

/// A linear minorant of a convex function.
///
/// A linear minorant of a convex function $f \colon \mathbb{R}\^n \to
/// \mathbb{R}$ is a linear function of the form
///
///   \\[ l \colon \mathbb{R}\^n \to \mathbb{R}, x \mapsto \langle g, x
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
    fn product(&self, other: &Self) -> Real {
        self.1.dot(&other.1)
    }

    fn add_scaled_to(&self, alpha: Real, target: &mut [Real]) {
        debug_assert_eq!(self.1.len(), target.len());
        if !alpha.is_zero() {
            for (x, y) in self.1.iter().zip(target) {
                *y += alpha * x;
            }
        }
    }

    fn move_center(&mut self, alpha: Real, d: &DVector) {
        self.0 += alpha * self.1.dot(d);
    }








<
|
<







107
108
109
110
111
112
113

114

115
116
117
118
119
120
121
    fn product(&self, other: &Self) -> Real {
        self.1.dot(&other.1)
    }

    fn add_scaled_to(&self, alpha: Real, target: &mut [Real]) {
        debug_assert_eq!(self.1.len(), target.len());
        if !alpha.is_zero() {

            BLAS1::add_scaled(target, alpha, &self.1);

        }
    }

    fn move_center(&mut self, alpha: Real, d: &DVector) {
        self.0 += alpha * self.1.dot(d);
    }

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    fn product(&self, other: &Self) -> Real {
        self.1.dot(&other.1)
    }

    fn add_scaled_to(&self, alpha: Real, target: &mut [Real]) {
        debug_assert_eq!(self.1.len(), target.len());
        if !alpha.is_zero() {
            for (x, y) in self.1.iter().zip(target) {
                *y += alpha * x;
            }
        }
    }

    fn move_center(&mut self, alpha: Real, d: &DVector) {
        self.0 += alpha * self.1.dot(d);
    }








<
|
<







151
152
153
154
155
156
157

158

159
160
161
162
163
164
165
    fn product(&self, other: &Self) -> Real {
        self.1.dot(&other.1)
    }

    fn add_scaled_to(&self, alpha: Real, target: &mut [Real]) {
        debug_assert_eq!(self.1.len(), target.len());
        if !alpha.is_zero() {

            BLAS1::add_scaled(target, alpha, &self.1);

        }
    }

    fn move_center(&mut self, alpha: Real, d: &DVector) {
        self.0 += alpha * self.1.dot(d);
    }

Changes to src/data/mod.rs.
12
13
14
15
16
17
18


19
20
21
22
23
24
25
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see  <http://www.gnu.org/licenses/>
 */

//! General types and data structures.



pub mod vector;
pub use vector::{DVector, Vector};

pub mod aggregatable;
pub use aggregatable::Aggregatable;








>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see  <http://www.gnu.org/licenses/>
 */

//! General types and data structures.

pub(crate) mod raw;

pub mod vector;
pub use vector::{DVector, Vector};

pub mod aggregatable;
pub use aggregatable::Aggregatable;

Added src/data/raw.rs.


































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
 * Copyright (c) 2020 Frank Fischer <frank-fischer@shadow-soft.de>
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see  <http://www.gnu.org/licenses/>
 */

///! BLAS-like low-level vector routines.

#[cfg(feature = "blas")]
use {openblas_src as _, rs_blas as blas, std::os::raw::c_int};

pub trait BLAS1<T> {
    /// Compute the inner product.
    fn dot(&self, y: &[T]) -> T;

    /// Compute the inner product.
    ///
    /// The inner product is computed on the smaller of the two
    /// dimensions. All other elements are assumed to be zero.
    fn dot_begin(&self, y: &[T]) -> T;

    /// Compute `self = self + alpha * y`.
    fn add_scaled(&mut self, alpha: T, y: &[T]);

    /// Return the 2-norm of this vector.
    fn norm2(&self) -> T;
}

impl BLAS1<f64> for [f64] {
    fn dot(&self, other: &[f64]) -> f64 {
        debug_assert_eq!(self.len(), other.len(), "Vectors must have the same size");
        Self::dot_begin(self, other)
    }

    fn dot_begin(&self, other: &[f64]) -> f64 {
        #[cfg(feature = "blas")]
        unsafe {
            blas::ddot(self.len().min(other.len()) as c_int, &self, 1, &other, 1)
        }
        #[cfg(not(feature = "blas"))]
        {
            self.iter().zip(other.iter()).map(|(x, y)| x * y).sum::<f64>()
        }
    }

    fn add_scaled(&mut self, alpha: f64, y: &[f64]) {
        assert_eq!(self.len(), y.len());
        #[cfg(feature = "blas")]
        unsafe {
            blas::daxpy(self.len() as c_int, alpha, &y, 1, &mut self[..], 1)
        }
        #[cfg(not(feature = "blas"))]
        {
            for (x, y) in self.iter_mut().zip(y.iter()) {
                *x += alpha * y;
            }
        }
    }

    fn norm2(&self) -> f64 {
        #[cfg(feature = "blas")]
        unsafe {
            blas::dnrm2(self.len() as c_int, &self, 1)
        }
        #[cfg(not(feature = "blas"))]
        {
            self.iter().map(|x| x * x).sum::<f64>().sqrt()
        }
    }
}
Changes to src/data/vector.rs.
1
2
3
4
5
6
7
8
// Copyright (c) 2016, 2017, 2018, 2019 Frank Fischer <frank-fischer@shadow-soft.de>
//
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
|







1
2
3
4
5
6
7
8
// Copyright (c) 2016-2020 Frank Fischer <frank-fischer@shadow-soft.de>
//
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
use num_traits::Zero;
use std::borrow::Borrow;
use std::fmt;
use std::iter::FromIterator;
use std::ops::{Deref, DerefMut};
use std::vec::IntoIter;

#[cfg(feature = "blas")]
use {openblas_src as _, rs_blas as blas, std::os::raw::c_int};

/// Type of dense vectors.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct DVector(pub Vec<Real>);

impl Deref for DVector {
    type Target = Vec<Real>;







<
|







20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
use num_traits::Zero;
use std::borrow::Borrow;
use std::fmt;
use std::iter::FromIterator;
use std::ops::{Deref, DerefMut};
use std::vec::IntoIter;


use super::raw::BLAS1;

/// Type of dense vectors.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct DVector(pub Vec<Real>);

impl Deref for DVector {
    type Target = Vec<Real>;
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
    }

    /// Return the inner product with another vector.
    ///
    /// The inner product is computed on the smaller of the two
    /// dimensions. All other elements are assumed to be zero.
    pub fn dot_begin(&self, other: &DVector) -> Real {
        #[cfg(feature = "blas")]
        unsafe {
            blas::ddot(self.len().min(other.len()) as c_int, &self, 1, &other, 1)
        }
        #[cfg(not(feature = "blas"))]
        {
            self.iter().zip(other.iter()).map(|(x, y)| x * y).sum::<Real>()
        }
    }

    /// Add two vectors and store result in this vector.
    pub fn add(&mut self, x: &DVector, y: &DVector) {
        assert_eq!(x.len(), y.len());
        self.clear();
        self.extend(x.iter().zip(y.iter()).map(|(a, b)| a + b));
    }

    /// Add two vectors and store result in this vector.
    pub fn add_scaled(&mut self, alpha: Real, y: &DVector) {
        assert_eq!(self.len(), y.len());
        #[cfg(feature = "blas")]
        unsafe {
            blas::daxpy(self.len() as c_int, alpha, &y, 1, &mut self[..], 1)
        }
        #[cfg(not(feature = "blas"))]
        {
            for (x, y) in self.iter_mut().zip(y.iter()) {
                *x += alpha * y;
            }
        }
    }

    /// Add two vectors and store result in this vector.
    ///
    /// In contrast to `add_scaled`, the two vectors might have
    /// different sizes. The size of the resulting vector is the
    /// larger of the two vector sizes and the remaining entries of
    /// the smaller vector are assumed to be 0.0.
    pub fn add_scaled_begin(&mut self, alpha: Real, y: &DVector) {
        #[cfg(feature = "blas")]
        unsafe {
            let n = self.len();
            blas::daxpy(n.min(y.len()) as c_int, alpha, &y, 1, &mut self[..], 1);
        }
        #[cfg(not(feature = "blas"))]
        {
            for (x, y) in self.iter_mut().zip(y.iter()) {
                *x += alpha * y;
            }
        }
        let n = self.len();
        if n < y.len() {
            self.extend(y[n..].iter().map(|y| alpha * y));
        }
    }

    /// Return the 2-norm of this vector.
    pub fn norm2(&self) -> Real {
        #[cfg(feature = "blas")]
        unsafe {
            blas::dnrm2(self.len() as c_int, &self, 1)
        }
        #[cfg(not(feature = "blas"))]
        {
            self.iter().map(|x| x * x).sum::<Real>().sqrt()
        }
    }
}

impl Aggregatable for DVector {
    fn new_scaled<A>(alpha: Real, other: A) -> Self
    where
        A: Borrow<Self>,







<
<
|
<
<
<
<
<











<
<
<
|
<
<
<
<
<
<
<









<
<
|
<
|
<
<
<
|
|
<
<
|






<
<
|
<
<
<
<
<







134
135
136
137
138
139
140


141





142
143
144
145
146
147
148
149
150
151
152



153







154
155
156
157
158
159
160
161
162


163

164



165
166


167
168
169
170
171
172
173


174





175
176
177
178
179
180
181
    }

    /// Return the inner product with another vector.
    ///
    /// The inner product is computed on the smaller of the two
    /// dimensions. All other elements are assumed to be zero.
    pub fn dot_begin(&self, other: &DVector) -> Real {


        BLAS1::dot_begin(&self[..], other)





    }

    /// Add two vectors and store result in this vector.
    pub fn add(&mut self, x: &DVector, y: &DVector) {
        assert_eq!(x.len(), y.len());
        self.clear();
        self.extend(x.iter().zip(y.iter()).map(|(a, b)| a + b));
    }

    /// Add two vectors and store result in this vector.
    pub fn add_scaled(&mut self, alpha: Real, y: &DVector) {



        BLAS1::add_scaled(&mut self[..], alpha, y);







    }

    /// Add two vectors and store result in this vector.
    ///
    /// In contrast to `add_scaled`, the two vectors might have
    /// different sizes. The size of the resulting vector is the
    /// larger of the two vector sizes and the remaining entries of
    /// the smaller vector are assumed to be 0.0.
    pub fn add_scaled_begin(&mut self, alpha: Real, y: &DVector) {


        let n = self.len().min(y.len());





        BLAS1::add_scaled(&mut self[..n], alpha, &y[..n]);



        if self.len() < y.len() {
            self.extend(y[n..].iter().map(|y| alpha * y));
        }
    }

    /// Return the 2-norm of this vector.
    pub fn norm2(&self) -> Real {


        BLAS1::norm2(&self[..])





    }
}

impl Aggregatable for DVector {
    fn new_scaled<A>(alpha: Real, other: A) -> Self
    where
        A: Borrow<Self>,