Rust doesn't see my overloaded f64 multiplication operator - operator-overloading

I'm implementing a simple matrix library in rust and I'm currently writing the operator for scalar multiplication. Right-multiplication works:
impl<T: Num + Zero + Clone + Float> Mul<T, Mat<T>> for Mat<T> {
fn mul(&self, rhs: &T) -> Mat<T> {
self.componentwise(|v| v.clone() * *rhs)
}
}
But I can't seem to do left-multiplication, I assumed the following code would do what I want:
impl<T: Num + Zero + Clone + Float> Mul<Mat<T>, Mat<T>> for T {
fn mul(&self, rhs: &Mat<T>) -> Mat<T> {
rhs.componentwise(|v| *self * v.clone())
}
}
But the following doesn't work:
let A = mat![[1f64, 2., 3.], [4., 5., 6.]];
let P = A * 4f64; // works!
let Q = 4f64 * A; // error...
The error is error: mismatched types: expected `f64`, found `linalg::Mat<f64>` (expected f64, found struct linalg::Mat). Can I only have f64 * f64 multiplication, or am I approaching the second case wrong? I tried implementing it for f64 specifically with impl Mul<Mat<f64>, Mat<f64>> for f64, but that still doesn't work.
I found that I could make it work using 4f64.mul(&A), but that is not ideal.

Maybe it is related with the declaration : your seconde impl declration is for Mult<Mat<T>, Mat<T>>, so my guess is that it permits to multiply two matrices, which is not what you want.
(I wanted to post a comment, but I cannot do this yet :()

Related

'+' is deprecated: Mixed-type addition is deprecated in Swift 3.1

When I'm directly adding an integer value(i.e: 1,2,3,etc) with another integer variable
let arr:Array = ["One","Two"]
var valueT:Int64 = 0
value = arr.count + 1 //in this line
I get the following warning:
'+' is deprecated: Mixed-type addition is deprecated. Please use explicit type conversion.
I fixed it the warning with this:
value = Int64(value + 1)
Though it is fixed but I wanna know why its called Mixed-type addition as I didn't use ++ . Also is there a better way to fix the warning in swift 3.1?
Update:
The following image is the proof of warning. I'm using Xcode Version 8.3 (8E162).
allROR is an array here.
Edit: To generate the error with your code it should be like
let value = 5
let result: Int64 = value + 1
Now you get the warning
'+' is deprecated: Mixed-type addition is deprecated. Please use explicit type conversion.
But it is looks like warning is misleading, as of both value and 1 is of type Int so its summation also Int so you need to simply convert the result to Int64 and it is what you doing and that is perfectly ok.
let result: Int64 = Int64(value + 1)
Just to answer this part: why its called Mixed-type addition
With the simplified example by Nirav D:
let value = 5
let result: Int64 = value + 1
You can Command-click on + and see the generated interface of Collection:
(After Indexing has finished, of course.)
#available(swift, deprecated: 3.0, obsoleted: 4.0, message: "Mixed-type addition is deprecated. Please use explicit type conversion.")
public func +<T>(lhs: T.Stride, rhs: T) -> T where T : SignedInteger
So, in the code example above, the type of 1 is inferred as Int64, and as Int64.Stride == Int, the operation value + 1 matches the signature func +<T>(lhs: T.Stride, rhs: T) -> T where T : SignedInteger.
This deprecation is included in the revised version of SE-0104 Protocol-oriented integers, this part:
Standard Library no longer provides + and - operators for Strideable types.
They were problematic, as one could have written mixed-type code like
let x: Int64 = 42; x += (1 as Int), which would compile, but
shouldn't. Besides, since the Stride of an unsigned type is signed,
Standard Library had to implement a hack to make code like let x: UInt
= 42; x += (1 as Int) ambiguous. These operators were only necessary because they made advancing collection indices convenient, which is no
longer the case since the introduction of the new indexing model in
Swift 3.
As you already have seen, you can avoid this warning in many ways.
Data type is different that is why it is showing an error
you need to make both variable and constant of same data type
for e.g.
let result = value + Int64(1) //in this line
OK
var arr = [String]()
var i: Int64 = 0
if arr.count == 0 {
i = 1
} else {
i = arr.count + 1
}
gives as a warning '+' is deprecated: Mixed-type addition is deprecated. Please use explicit type conversion.
The reason is, that arr.count and i has different types. And this warning is right. It has nothing with the integer literal 1
this snippet gives you the warning too
var arr = [String]()
var i: Int64 = 0
if arr.count == 0 {
i = 1
} else {
i = 1
i += arr.count // here is the warning now
}
this will not compile, even though it looks very similar
var arr = [String]()
var i: Int64 = 0
if arr.count == 0 {
i = 1
} else {
let tmp = arr.count + 1
i = tmp
}
I hope we get an error message when we compose all of these snippets in the future release.

Cannot match values of type

I'm just starting out with Swift 3 and I'm converting a Rails project to swift (side project while I learn)
Fairly simple, I have a Rails statement Im converting and Im getting many red errors in Xcode:
let startingPoint: Int = 1
let firstRange: ClosedRange = (2...10)
let secondRange: ClosedRange = (11...20)
func calc(range: Float) -> Float {
switch range {
case startingPoint:
return (range - startingPoint) * 1 // or 0.2
case firstRange:
return // code
default:
return //code
}
}
calc will either have an Int or Float value: 10 or 10.50
Errors are:
Expression pattern of type ClosedRange cannot match values of type Float
Binary operator - cannot be applied to operands of type Float and Int
I understand the errors but I dont know what to search for to correct it. Could you point me in the right direction, please?
Swift is strongly typed. Whenever you use a variable or pass something as a function argument, Swift checks that it is of the correct type. You can't pass a string to a function that expects an integer etc. Swift does this check at compile time (since it's statically typed).
To adhere by that rules, try changing your code to this:
let startingPoint: Float = 1
let firstRange: ClosedRange<Float> = (2...10)
let secondRange: ClosedRange<Float> = (11...20)
func calc(range: Float) -> Float {
switch range {
case startingPoint:
return (range - startingPoint) * 1 // or 0.2
case firstRange:
return 1.0 // 1.0 is just an example, but you have to return Float since that is defined in the method
default:
return 0.0 // 0.0 is just an example, put whatever you need here
}
}
For the first error, you might want to specify ClosedRange to be of type Floats. Something similar to:
let firstRange: ClosedRange<Float> = (2...10)
For the second error, the problem is you are trying to compare a Float (range:Float) with an Int (startingPoint). So I would suggest you convert the startingPoint variable to a Float as well.

No * candidates produce the expected contextual result type 'FloatingPointRoundRule' [duplicate]

I have the following simple extension to Double, which worked fine in everything up to Xcode 8 beta 3
public extension Double {
public func roundTo(_ decimalPlaces: Int) -> Double {
var v = self
var divisor = 1.0
if decimalPlaces > 0 {
for _ in 1 ... decimalPlaces {
v *= 10.0
divisor *= 0.1
}
}
return round(v) * divisor
}
}
As of Beta 4, I am getting "Cannot use mutating member on immutable value: 'self' is immutable" on the round function in the return - has anyone got any clues?
This is due to a naming conflict with the new rounding functions on the FloatingPoint protocol, round() and rounded(), which have been added to Swift 3 as of Xcode 8 beta 4.
You therefore either need to disambiguate by specifying that you're referring to global round() function in the Darwin module:
return Darwin.round(v) * divisor
Or, even better, simply make use of the new rounding functions and call rounded() on v:
return v.rounded() * divisor

Conforming String.CharacterView.Index to Strideable: fatal error when using stride(to:by:): "cannot increment endIndex "

Question:
When attempting to stride over String.CharacterView.Index indices by e.g. a stride of 2
extension String.CharacterView.Index : Strideable { }
let str = "01234"
for _ in str.startIndex.stride(to: str.endIndex, by: 2) { } // fatal error
I get the following runtime exception
fatal error: cannot increment endIndex
Just creating the StrideTo<String.CharacterView.Index> above, however, (let foo = str.startIndex.stride(to: str.endIndex, by: 2)) does not yield an error, only when attempting to stride/iterate over or operate on it (.next()?).
What is the reason for this runtime exception; is it expected (mis-use of conformance to Stridable)?
I'm using Swift 2.2 and Xcode 7.3. Details follow below.
Edit addition: error source located
Upon reading my question carefully, it would seem as if the error really does occur in the next() method of StrideToGenerator (see bottom of this post), specifically at the following marked line
let ret = current
current += stride // <-- here
return ret
Even if the last update of current will never be returned (in next call to next()), the final advance of current index to a value larger or equal to that of _end yields the specific runtime error above (for Index type String.CharacterView.Index).
(0..<4).startIndex.advancedBy(4) // OK, -> 4
"foo".startIndex.advancedBy(4) // fatal error: cannot increment endIndex
However, one question still remains:
Is this a bug in the next() method of StrideToGenerator, or just an error that pops up due to a mis-use of String.CharacterView.Index conformance to Stridable?
Related
The following Q&A is related to the subject of a iterating over characters in steps other than +1, and worth including in this question even if the two questions differ.
Using String.CharacterView.Index.successor() in for statements
Especially note #Sulthan:s neat solution in the thread above.
Details
(Apologies for hefty details/investigations of my own, just skip these sections if you can answer my question without the details herein)
The String.CharacterView.Index type describes a character position, and:
conforms to Comparable (and in so, Equatable),
contains implementations for advancedBy(_:) and distanceTo(_:).
Hence, it can directly be made to conform to the protocol Strideable, making use of Stridable:s default implementations of methods stride(through:by:) and stride(to:by:). The examples below will focus on the latter (analogous problems with the former):
...
func stride(to end: Self, by stride: Self.Stride) -> StrideTo<Self>
Returns the sequence of values (self, self + stride, self + stride +
stride, ... last) where last is the last value in the progression
that is less than end.
Conforming to Stridable and striding by 1: all good
Extending String.CharacterView.Index to Stridable and striding by 1 works fine:
extension String.CharacterView.Index : Strideable { }
var str = "0123"
// stride by 1: all good
str.startIndex.stride(to: str.endIndex, by: 1).forEach {
print($0,str.characters[$0])
} /* 0 0
1 1
2 2
3 3 */
For an even number of indices in str above (indices 0..<4), this also works for a stride of 2:
// stride by 2: OK for even number of characters in str.
str.startIndex.stride(to: str.endIndex, by: 2).forEach {
print($0,str.characters[$0])
} /* 0 0
2 2 */
However, for some cases of striding by >1: runtime exception
For an odd number of indices and a stride of 2, however, the stride over the character views indices yield a runtime error
// stride by 2: fatal error for odd number of characters in str.
str = "01234"
str.startIndex.stride(to: str.endIndex, by: 2).forEach {
print($0,str.characters[$0])
} /* 0 0
2 2
fatal error: cannot increment endIndex */
Investigations of my own
My own investigations into this made me suspect the error comes from the next() method of the StrideToGenerator structure, possibly when this method calls += on the stridable element
public func += <T : Strideable>(inout lhs: T, rhs: T.Stride) {
lhs = lhs.advancedBy(rhs)
}
(from a version of the Swift source for swift/stdlib/public/core/Stride.swift that somewhat corresponds to Swift 2.2). Given the following Q&A:s
Trim end off of string in swift, getting error at runtime,
Swift distance() method throws fatal error: can not increment endIndex,
we could suspect that we would possibly need to use String.CharacterView.Index.advancedBy(_:limit:) rather than ...advancedBy(_:) above. However from what I can see, the next() method in StrideToGenerator guards against advancing the index past the limit.
Edit addition: the source of the error seems to indeed be located in the next() method in StrideToGenerator:
// ... in StrideToGenerator
public mutating func next() -> Element? {
if stride > 0 ? current >= end : current <= end {
return nil
}
let ret = current
current += stride /* <-- will increase current to larger or equal to end
if stride is large enough (even if this last current
will never be returned in next call to next()) */
return ret
}
Even if the last update of current will never be returned (in next call to next()), the final advance of current index to a value larger or equal to that of end yields the specific runtime error above, for Index type String.CharacterView.Index.
(0..<4).startIndex.advancedBy(4) // OK, -> 4
"foo".startIndex.advancedBy(4) // fatal error: cannot increment endIndex
Is this to be considered a bug, or is String.CharacterView.Index simply not intended to be (directly) conformed to Stridable?
Simply declaring the protocol conformance
extension String.CharacterView.Index : Strideable { }
compiles because String.CharacterView.Index conforms to
BidirectionalIndexType , and ForwardIndexType/BidirectionalIndexType have default method implementations for advancedBy() and distanceTo()
as required by Strideable.
Strideable has the default protocol method implementation
for stride():
extension Strideable {
// ...
public func stride(to end: Self, by stride: Self.Stride) -> StrideTo<Self>
}
So the only methods which are "directly" implemented for
String.CharacterView.Index are – as far as I can see - the successor() and predecessor() methods from BidirectionalIndexType.
As you already figured out, the default method implementation of
stride() does not work well with String.CharacterView.Index.
But is is always possible to define dedicated methods for a concrete type. For the problems of making String.CharacterView.Index conform to Strideable see
Vatsal Manot's answer below and the discussion in the comments – it took me a while to get what he meant :)
Here is a possible implementation of a stride(to:by:) method for String.CharacterView.Index:
extension String.CharacterView.Index {
typealias Index = String.CharacterView.Index
func stride(to end: Index, by stride: Int) -> AnySequence<Index> {
precondition(stride != 0, "stride size must not be zero")
return AnySequence { () -> AnyGenerator<Index> in
var current = self
return AnyGenerator {
if stride > 0 ? current >= end : current <= end {
return nil
}
defer {
current = current.advancedBy(stride, limit: end)
}
return current
}
}
}
}
This seems to work as expected:
let str = "01234"
str.startIndex.stride(to: str.endIndex, by: 2).forEach {
print($0,str.characters[$0])
}
Output
0 0
2 2
4 4
To simply answer your ending question: this is not a bug. This is normal behavior.
String.CharacterView.Index can never exceed the endIndex of the parent construct (i.e. the character view), and thus triggers a runtime error when forced to (as correctly noted in the latter part of your answer). This is by design.
The only solution is to write your own alternative to the stride(to:by:), one that avoids equalling or exceeding the endIndex in any way.
As you know already, you can technically implement Strideable, but you cannot prevent that error. And since stride(to:by:) is not blueprinted within the protocol itself but introduced in an extension, there is no way you can use a "custom" stride(to:by:) in a generic scope (i.e. <T: Strideable> etc.). Which means you should probably not try and implement it unless you are absolutely sure that there is no way that error can occur; something which seems impossible.
Solution: There isn't one, currently. However, if you feel that this is an issue, I encourage you to start a thread in the swift-evolution mailing list, where this topic would be best received.
This isn't really an answer; it's just that your question got me playing around. Let's ignore Stridable and just try striding through a character view:
let str = "01234"
var i = str.startIndex
// i = i.advancedBy(1)
let inc = 2
while true {
print(str.characters[i])
if i.distanceTo(str.endIndex) > inc {
i = i.advancedBy(inc)
} else {
break
}
}
As you can see, it is crucial to test with distanceTo before we call advancedBy. Otherwise, we risk attempting to advance right through the end index and we'll get the "fatal error: can not increment endIndex" bomb.
So my thought is that something like this must be necessary in order to make the indices of a character view stridable.

rust calling failure::fail_bounds_check with no-landing-pads flag enabled

I have been trying to write a basic kernel in rust and the link script fails with the following error:
roost.rs:(.text.kmain+0x12a): undefined reference to 'failure::fail_bounds_check::hee3207bbe41f708990v::v0.11.0'
I compile the rust source files with the following flags:
-O --target i686-unknown-linux-gnu -Z no-landing-pads --crate-type lib --emit=obj
If I understand the rust compiler correctly the -Z no-landing-pads option should stop the compiler from generating the failure functions. From testing I can tell that the failure function is only generated when the kmain function calls my function io::write_char(c: char)
This is the definition of io::write_char(c: char)
pub fn write_char(c: char) {
unsafe {
vga::place_char_at(c, vga::cursor_x, vga::cursor_y);
vga::cursor_y =
if vga::cursor_x >= vga::VGA_WIDTH {
vga::cursor_y + 1
} else {
vga::cursor_y
};
vga::cursor_x =
if vga::cursor_x >= vga::VGA_WIDTH {
0
} else {
vga::cursor_x + 1
};
vga::set_cursor_location(vga::cursor_x, vga::cursor_y);
}
}
How can I stop rust from trying to call the nonexistant function failure::fail_bounds_check?
Edit: further testing indicates that the vga::place_char_at function is the cause. Here is the code:
pub fn place_char_at(c: char, x: u8, y: u8) {
let tmpx =
if x >= VGA_WIDTH {
VGA_WIDTH - 1
} else {
x
};
let tmpy =
if y >= VGA_HEIGHT {
VGA_HEIGHT - 1
} else {
y
};
unsafe {
(*SCREEN)[(tmpy as uint) * 80 + (tmpx as uint)].char = c as u8;
}
}
From what I can tell the issue is that rust wants to bound check the array access I'm doing, is there a way to turn the assure the compiler that the checks have been done or turn off the feature for that function?
Edit2: So I solved it after some work. After digging around in the docs I found that rust has a function for vector access that bypasses bound checking. To use it I changed the place_char_at function to this:
pub fn place_char_at(c: char, x: u8, y: u8) {
let tmpx =
if x >= VGA_WIDTH {
VGA_WIDTH - 1
} else {
x
};
let tmpy =
if y >= VGA_HEIGHT {
VGA_HEIGHT - 1
} else {
y
};
unsafe {
(*SCREEN).unsafe_mut_ref((tmpy as uint) * 80 + (tmpx as uint)).char = c as u8;
}
}
Make sure you're linking to libcore. Also libcore has one dependency: a definition of failure. Make sure you mark a function #[lang="begin_unwind"] somewhere in your exception code. The requirement is that begin_unwind not return. See here for my example.
is there a way to ... turn off the feature for that function?
Nope. In the words of bstrie, if there were a compiler flag to eliminate array bounds checks, then bstrie would fork the language and make the flag delete your hard drive. In other words, safety is paramount.
You haven't described the type of SCREEN but if it implements MutableVector trait, what you probably want is to use an unsafe_set ( http://doc.rust-lang.org/core/slice/trait.MutableVector.html#tymethod.unsafe_set ):
unsafe fn unsafe_set(self, index: uint, val: T)
This performs no bounds checks, and it is undefined behaviour if index is larger than the length of self. However, it does run the destructor at index. It is equivalent to self[index] = val.