Octave: How to sum(A .* B, 3) without expanding A .* B?How do I create a simple Octave distributable without installing OctaveSumming diagonal elements of matrix in Octaveexpand, factor and simplify on OctaveGradient Descent implementation in octaveDifferences between Octave and MATLAB?Summing a single row vector by column in OctaveBasic for loop in Octave expandedSum of anonymous functions in OctaveHow to prevent Octave from summing row and column vectors?sum elements of vector excluding the first element in Octave
Are illustrations in novels frowned upon?
In an emergency, how do I find and share my position?
What are some interesting features that are common cross-linguistically but don't exist in English?
Who was president?
Did it used to be possible to target a zone?
Is it possible to get crispy, crunchy carrots from canned carrots?
Why did MS-DOS applications built using Turbo Pascal fail to start with a division by zero error on faster systems?
What is the difference between true neutral and unaligned?
Photoshop CS6 - Remove glare/hue from image
Is a player able to change alignment midway through an adventure?
Why does trim() NOT remove char 160?
Cross-referencing enumerate item
Why were movies shot on film shot at 24 frames per second?
Please help me identify the bold slashes between staves
Compelling story with the world as a villain
Prove your innocence
Avoiding racist tropes in fantasy
Was there ever a treaty between 2 entities with significantly different translations to the detriment of one party?
Can pay be witheld for hours cleaning up after closing time?
What is the best option for High availability on a data warehouse?
Is it safe to remove the bottom chords of a series of garage roof trusses?
Would it be possible to have a GMO that produces chocolate?
C++20 constexpr std::copy optimizations for run-time
Is there any practical application for performing a double Fourier transform? ...or an inverse Fourier transform on a time-domain input?
Octave: How to sum(A .* B, 3) without expanding A .* B?
How do I create a simple Octave distributable without installing OctaveSumming diagonal elements of matrix in Octaveexpand, factor and simplify on OctaveGradient Descent implementation in octaveDifferences between Octave and MATLAB?Summing a single row vector by column in OctaveBasic for loop in Octave expandedSum of anonymous functions in OctaveHow to prevent Octave from summing row and column vectors?sum elements of vector excluding the first element in Octave
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
Consider the following scenario, for A with size [k, 1, m] and B with size [1, n, m], how can one get the same result as:
C = sum(A .* B, 3);
without expanding
A .* B
Because that takes way too much memory.
Something like the following loop but natively:
C = zeros(k,n);
for idx = 1:m
C += A(:,1,idx) * B(1,:,idx);
end
I guess I could also ask if there's a function like bsxfun with a "reduce"-like behavior?
Something like:
C = bsxfun_accumulate(@(a, b) a * b, A, B);
Note: by native I mean cs/cuda code-paths, or opencl code-path, or x86-sse, or plain x86 instructions. Whatever is available.
octave
|
show 1 more comment
Consider the following scenario, for A with size [k, 1, m] and B with size [1, n, m], how can one get the same result as:
C = sum(A .* B, 3);
without expanding
A .* B
Because that takes way too much memory.
Something like the following loop but natively:
C = zeros(k,n);
for idx = 1:m
C += A(:,1,idx) * B(1,:,idx);
end
I guess I could also ask if there's a function like bsxfun with a "reduce"-like behavior?
Something like:
C = bsxfun_accumulate(@(a, b) a * b, A, B);
Note: by native I mean cs/cuda code-paths, or opencl code-path, or x86-sse, or plain x86 instructions. Whatever is available.
octave
5
What do you mean by "but natively"? Loops are native to MATLAB, and not necessarily slow. You just need to useC = C + ...
rather than+=
which isn't valid MATLAB syntax.
– Wolfie
Mar 27 at 16:46
1
In addition to what Wolfie said, you also want to use*
(matrix multiplication) instead of.*
(element-wise multiplication) in your for loop.
– gnovice
Mar 27 at 16:55
By native I mean machine code. x86 or gpu code, definitely not interpreted. I changed the title to Octave only as my impression is that Matlab was much slower than octave. Is Matlab running on jvm or machine code?
– hackdev
Mar 27 at 16:55
3
@hackdev I doubt MATLAB is slower than octave. Recent JIT compilers of MATLAB make it run as fast as native code. Also most of the operations (such as.*
) are not run in MATLAB code, but in the underlying Fotran accelerated multi-threaded inbuilt function. MATLAB is fast for matrix operations, almost unbeatable fast. It also has the option of running most of the basic operations on the GPU.
– Ander Biguri
Mar 27 at 17:02
2
If Octave was faster than MATLAB, The MathWorks would go out of business... I don't understand why this is your assumption?
– Wolfie
Mar 27 at 17:06
|
show 1 more comment
Consider the following scenario, for A with size [k, 1, m] and B with size [1, n, m], how can one get the same result as:
C = sum(A .* B, 3);
without expanding
A .* B
Because that takes way too much memory.
Something like the following loop but natively:
C = zeros(k,n);
for idx = 1:m
C += A(:,1,idx) * B(1,:,idx);
end
I guess I could also ask if there's a function like bsxfun with a "reduce"-like behavior?
Something like:
C = bsxfun_accumulate(@(a, b) a * b, A, B);
Note: by native I mean cs/cuda code-paths, or opencl code-path, or x86-sse, or plain x86 instructions. Whatever is available.
octave
Consider the following scenario, for A with size [k, 1, m] and B with size [1, n, m], how can one get the same result as:
C = sum(A .* B, 3);
without expanding
A .* B
Because that takes way too much memory.
Something like the following loop but natively:
C = zeros(k,n);
for idx = 1:m
C += A(:,1,idx) * B(1,:,idx);
end
I guess I could also ask if there's a function like bsxfun with a "reduce"-like behavior?
Something like:
C = bsxfun_accumulate(@(a, b) a * b, A, B);
Note: by native I mean cs/cuda code-paths, or opencl code-path, or x86-sse, or plain x86 instructions. Whatever is available.
octave
octave
edited Mar 27 at 17:02
hackdev
asked Mar 27 at 16:43
hackdevhackdev
3082 silver badges7 bronze badges
3082 silver badges7 bronze badges
5
What do you mean by "but natively"? Loops are native to MATLAB, and not necessarily slow. You just need to useC = C + ...
rather than+=
which isn't valid MATLAB syntax.
– Wolfie
Mar 27 at 16:46
1
In addition to what Wolfie said, you also want to use*
(matrix multiplication) instead of.*
(element-wise multiplication) in your for loop.
– gnovice
Mar 27 at 16:55
By native I mean machine code. x86 or gpu code, definitely not interpreted. I changed the title to Octave only as my impression is that Matlab was much slower than octave. Is Matlab running on jvm or machine code?
– hackdev
Mar 27 at 16:55
3
@hackdev I doubt MATLAB is slower than octave. Recent JIT compilers of MATLAB make it run as fast as native code. Also most of the operations (such as.*
) are not run in MATLAB code, but in the underlying Fotran accelerated multi-threaded inbuilt function. MATLAB is fast for matrix operations, almost unbeatable fast. It also has the option of running most of the basic operations on the GPU.
– Ander Biguri
Mar 27 at 17:02
2
If Octave was faster than MATLAB, The MathWorks would go out of business... I don't understand why this is your assumption?
– Wolfie
Mar 27 at 17:06
|
show 1 more comment
5
What do you mean by "but natively"? Loops are native to MATLAB, and not necessarily slow. You just need to useC = C + ...
rather than+=
which isn't valid MATLAB syntax.
– Wolfie
Mar 27 at 16:46
1
In addition to what Wolfie said, you also want to use*
(matrix multiplication) instead of.*
(element-wise multiplication) in your for loop.
– gnovice
Mar 27 at 16:55
By native I mean machine code. x86 or gpu code, definitely not interpreted. I changed the title to Octave only as my impression is that Matlab was much slower than octave. Is Matlab running on jvm or machine code?
– hackdev
Mar 27 at 16:55
3
@hackdev I doubt MATLAB is slower than octave. Recent JIT compilers of MATLAB make it run as fast as native code. Also most of the operations (such as.*
) are not run in MATLAB code, but in the underlying Fotran accelerated multi-threaded inbuilt function. MATLAB is fast for matrix operations, almost unbeatable fast. It also has the option of running most of the basic operations on the GPU.
– Ander Biguri
Mar 27 at 17:02
2
If Octave was faster than MATLAB, The MathWorks would go out of business... I don't understand why this is your assumption?
– Wolfie
Mar 27 at 17:06
5
5
What do you mean by "but natively"? Loops are native to MATLAB, and not necessarily slow. You just need to use
C = C + ...
rather than +=
which isn't valid MATLAB syntax.– Wolfie
Mar 27 at 16:46
What do you mean by "but natively"? Loops are native to MATLAB, and not necessarily slow. You just need to use
C = C + ...
rather than +=
which isn't valid MATLAB syntax.– Wolfie
Mar 27 at 16:46
1
1
In addition to what Wolfie said, you also want to use
*
(matrix multiplication) instead of .*
(element-wise multiplication) in your for loop.– gnovice
Mar 27 at 16:55
In addition to what Wolfie said, you also want to use
*
(matrix multiplication) instead of .*
(element-wise multiplication) in your for loop.– gnovice
Mar 27 at 16:55
By native I mean machine code. x86 or gpu code, definitely not interpreted. I changed the title to Octave only as my impression is that Matlab was much slower than octave. Is Matlab running on jvm or machine code?
– hackdev
Mar 27 at 16:55
By native I mean machine code. x86 or gpu code, definitely not interpreted. I changed the title to Octave only as my impression is that Matlab was much slower than octave. Is Matlab running on jvm or machine code?
– hackdev
Mar 27 at 16:55
3
3
@hackdev I doubt MATLAB is slower than octave. Recent JIT compilers of MATLAB make it run as fast as native code. Also most of the operations (such as
.*
) are not run in MATLAB code, but in the underlying Fotran accelerated multi-threaded inbuilt function. MATLAB is fast for matrix operations, almost unbeatable fast. It also has the option of running most of the basic operations on the GPU.– Ander Biguri
Mar 27 at 17:02
@hackdev I doubt MATLAB is slower than octave. Recent JIT compilers of MATLAB make it run as fast as native code. Also most of the operations (such as
.*
) are not run in MATLAB code, but in the underlying Fotran accelerated multi-threaded inbuilt function. MATLAB is fast for matrix operations, almost unbeatable fast. It also has the option of running most of the basic operations on the GPU.– Ander Biguri
Mar 27 at 17:02
2
2
If Octave was faster than MATLAB, The MathWorks would go out of business... I don't understand why this is your assumption?
– Wolfie
Mar 27 at 17:06
If Octave was faster than MATLAB, The MathWorks would go out of business... I don't understand why this is your assumption?
– Wolfie
Mar 27 at 17:06
|
show 1 more comment
1 Answer
1
active
oldest
votes
You can actually solve your problem by simply reshaping the variables A
and B
and applying a matrix multiply:
C = reshape(A, [], m)*(reshape(B, [], m).');
Basically, summing the results of m
sets of multiplications involving k
-by-1 column vectors and 1-by-n
row vectors is the equivalent of multiplying a k
-by-m
matrix of your columns and an m
-by-n
matrix of your rows.
Gee, that not only seems to work, it's actually ridiculously fast compared to the loop. I would give you two votes, but I can only vote once. XD
– hackdev
Mar 27 at 17:09
@hackdev as asker of the question, you can mark the answer as "accepted", thereby closing the question and awarding 1.5x the reputation points of an upvote.
– Wolfie
Mar 27 at 17:17
I was having issues with this question because I have a corner case where A is [k, 1, 1], where matrix multiplication doesn't work. So I realized that .* always works. But in practice it explodes for large matrices. Basically adding an if size(A,3)==1 solves the whole issue. :)
– hackdev
Mar 27 at 17:25
@hackdev: If you are faced with a case whereA
is size[k 1 1]
butB
is still size[1 n m]
, here's one way to solve it like above:C = repmat(A, 1, m)*(reshape(B, [], m).');
– gnovice
Mar 27 at 17:31
That last corner case works well by usingA * sum(B')
, but I'll measure to see which is faster.
– hackdev
Mar 27 at 17:31
|
show 2 more comments
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55382450%2foctave-how-to-suma-b-3-without-expanding-a-b%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can actually solve your problem by simply reshaping the variables A
and B
and applying a matrix multiply:
C = reshape(A, [], m)*(reshape(B, [], m).');
Basically, summing the results of m
sets of multiplications involving k
-by-1 column vectors and 1-by-n
row vectors is the equivalent of multiplying a k
-by-m
matrix of your columns and an m
-by-n
matrix of your rows.
Gee, that not only seems to work, it's actually ridiculously fast compared to the loop. I would give you two votes, but I can only vote once. XD
– hackdev
Mar 27 at 17:09
@hackdev as asker of the question, you can mark the answer as "accepted", thereby closing the question and awarding 1.5x the reputation points of an upvote.
– Wolfie
Mar 27 at 17:17
I was having issues with this question because I have a corner case where A is [k, 1, 1], where matrix multiplication doesn't work. So I realized that .* always works. But in practice it explodes for large matrices. Basically adding an if size(A,3)==1 solves the whole issue. :)
– hackdev
Mar 27 at 17:25
@hackdev: If you are faced with a case whereA
is size[k 1 1]
butB
is still size[1 n m]
, here's one way to solve it like above:C = repmat(A, 1, m)*(reshape(B, [], m).');
– gnovice
Mar 27 at 17:31
That last corner case works well by usingA * sum(B')
, but I'll measure to see which is faster.
– hackdev
Mar 27 at 17:31
|
show 2 more comments
You can actually solve your problem by simply reshaping the variables A
and B
and applying a matrix multiply:
C = reshape(A, [], m)*(reshape(B, [], m).');
Basically, summing the results of m
sets of multiplications involving k
-by-1 column vectors and 1-by-n
row vectors is the equivalent of multiplying a k
-by-m
matrix of your columns and an m
-by-n
matrix of your rows.
Gee, that not only seems to work, it's actually ridiculously fast compared to the loop. I would give you two votes, but I can only vote once. XD
– hackdev
Mar 27 at 17:09
@hackdev as asker of the question, you can mark the answer as "accepted", thereby closing the question and awarding 1.5x the reputation points of an upvote.
– Wolfie
Mar 27 at 17:17
I was having issues with this question because I have a corner case where A is [k, 1, 1], where matrix multiplication doesn't work. So I realized that .* always works. But in practice it explodes for large matrices. Basically adding an if size(A,3)==1 solves the whole issue. :)
– hackdev
Mar 27 at 17:25
@hackdev: If you are faced with a case whereA
is size[k 1 1]
butB
is still size[1 n m]
, here's one way to solve it like above:C = repmat(A, 1, m)*(reshape(B, [], m).');
– gnovice
Mar 27 at 17:31
That last corner case works well by usingA * sum(B')
, but I'll measure to see which is faster.
– hackdev
Mar 27 at 17:31
|
show 2 more comments
You can actually solve your problem by simply reshaping the variables A
and B
and applying a matrix multiply:
C = reshape(A, [], m)*(reshape(B, [], m).');
Basically, summing the results of m
sets of multiplications involving k
-by-1 column vectors and 1-by-n
row vectors is the equivalent of multiplying a k
-by-m
matrix of your columns and an m
-by-n
matrix of your rows.
You can actually solve your problem by simply reshaping the variables A
and B
and applying a matrix multiply:
C = reshape(A, [], m)*(reshape(B, [], m).');
Basically, summing the results of m
sets of multiplications involving k
-by-1 column vectors and 1-by-n
row vectors is the equivalent of multiplying a k
-by-m
matrix of your columns and an m
-by-n
matrix of your rows.
edited Mar 27 at 17:23
answered Mar 27 at 17:02
gnovicegnovice
120k13 gold badges237 silver badges341 bronze badges
120k13 gold badges237 silver badges341 bronze badges
Gee, that not only seems to work, it's actually ridiculously fast compared to the loop. I would give you two votes, but I can only vote once. XD
– hackdev
Mar 27 at 17:09
@hackdev as asker of the question, you can mark the answer as "accepted", thereby closing the question and awarding 1.5x the reputation points of an upvote.
– Wolfie
Mar 27 at 17:17
I was having issues with this question because I have a corner case where A is [k, 1, 1], where matrix multiplication doesn't work. So I realized that .* always works. But in practice it explodes for large matrices. Basically adding an if size(A,3)==1 solves the whole issue. :)
– hackdev
Mar 27 at 17:25
@hackdev: If you are faced with a case whereA
is size[k 1 1]
butB
is still size[1 n m]
, here's one way to solve it like above:C = repmat(A, 1, m)*(reshape(B, [], m).');
– gnovice
Mar 27 at 17:31
That last corner case works well by usingA * sum(B')
, but I'll measure to see which is faster.
– hackdev
Mar 27 at 17:31
|
show 2 more comments
Gee, that not only seems to work, it's actually ridiculously fast compared to the loop. I would give you two votes, but I can only vote once. XD
– hackdev
Mar 27 at 17:09
@hackdev as asker of the question, you can mark the answer as "accepted", thereby closing the question and awarding 1.5x the reputation points of an upvote.
– Wolfie
Mar 27 at 17:17
I was having issues with this question because I have a corner case where A is [k, 1, 1], where matrix multiplication doesn't work. So I realized that .* always works. But in practice it explodes for large matrices. Basically adding an if size(A,3)==1 solves the whole issue. :)
– hackdev
Mar 27 at 17:25
@hackdev: If you are faced with a case whereA
is size[k 1 1]
butB
is still size[1 n m]
, here's one way to solve it like above:C = repmat(A, 1, m)*(reshape(B, [], m).');
– gnovice
Mar 27 at 17:31
That last corner case works well by usingA * sum(B')
, but I'll measure to see which is faster.
– hackdev
Mar 27 at 17:31
Gee, that not only seems to work, it's actually ridiculously fast compared to the loop. I would give you two votes, but I can only vote once. XD
– hackdev
Mar 27 at 17:09
Gee, that not only seems to work, it's actually ridiculously fast compared to the loop. I would give you two votes, but I can only vote once. XD
– hackdev
Mar 27 at 17:09
@hackdev as asker of the question, you can mark the answer as "accepted", thereby closing the question and awarding 1.5x the reputation points of an upvote.
– Wolfie
Mar 27 at 17:17
@hackdev as asker of the question, you can mark the answer as "accepted", thereby closing the question and awarding 1.5x the reputation points of an upvote.
– Wolfie
Mar 27 at 17:17
I was having issues with this question because I have a corner case where A is [k, 1, 1], where matrix multiplication doesn't work. So I realized that .* always works. But in practice it explodes for large matrices. Basically adding an if size(A,3)==1 solves the whole issue. :)
– hackdev
Mar 27 at 17:25
I was having issues with this question because I have a corner case where A is [k, 1, 1], where matrix multiplication doesn't work. So I realized that .* always works. But in practice it explodes for large matrices. Basically adding an if size(A,3)==1 solves the whole issue. :)
– hackdev
Mar 27 at 17:25
@hackdev: If you are faced with a case where
A
is size [k 1 1]
but B
is still size [1 n m]
, here's one way to solve it like above: C = repmat(A, 1, m)*(reshape(B, [], m).');
– gnovice
Mar 27 at 17:31
@hackdev: If you are faced with a case where
A
is size [k 1 1]
but B
is still size [1 n m]
, here's one way to solve it like above: C = repmat(A, 1, m)*(reshape(B, [], m).');
– gnovice
Mar 27 at 17:31
That last corner case works well by using
A * sum(B')
, but I'll measure to see which is faster.– hackdev
Mar 27 at 17:31
That last corner case works well by using
A * sum(B')
, but I'll measure to see which is faster.– hackdev
Mar 27 at 17:31
|
show 2 more comments
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55382450%2foctave-how-to-suma-b-3-without-expanding-a-b%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
What do you mean by "but natively"? Loops are native to MATLAB, and not necessarily slow. You just need to use
C = C + ...
rather than+=
which isn't valid MATLAB syntax.– Wolfie
Mar 27 at 16:46
1
In addition to what Wolfie said, you also want to use
*
(matrix multiplication) instead of.*
(element-wise multiplication) in your for loop.– gnovice
Mar 27 at 16:55
By native I mean machine code. x86 or gpu code, definitely not interpreted. I changed the title to Octave only as my impression is that Matlab was much slower than octave. Is Matlab running on jvm or machine code?
– hackdev
Mar 27 at 16:55
3
@hackdev I doubt MATLAB is slower than octave. Recent JIT compilers of MATLAB make it run as fast as native code. Also most of the operations (such as
.*
) are not run in MATLAB code, but in the underlying Fotran accelerated multi-threaded inbuilt function. MATLAB is fast for matrix operations, almost unbeatable fast. It also has the option of running most of the basic operations on the GPU.– Ander Biguri
Mar 27 at 17:02
2
If Octave was faster than MATLAB, The MathWorks would go out of business... I don't understand why this is your assumption?
– Wolfie
Mar 27 at 17:06