How to prevent destruction of references to local variables in Rust? - memory

I have two structures. First is Point with two i32 coordinates, second is a Line with references to two Points. Structures have new and random constructors.
Required usage is:
use sandbox::{Point, Line};
fn main() {
let line = Line::new(&Point::new(1, 2),
&Point::new(1, 2));
line.from; // error[E0716]: temporary value dropped while borrowed
Line::random(10, 10); // error[E0515]: cannot return value referencing local variable `a`
}
And structs:
use rand::Rng;
pub struct Point {
pub x: i32,
pub y: i32,
}
pub struct Line<'line> {
pub from: &'line Point,
pub to: &'line Point,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
}
impl<'line> Line<'line> {
pub fn new<'a>(from: &'a Point, to: &'a Point) -> Line<'a> {
Line { from, to }
}
pub fn random<'a>(img_width: i32, img_height: i32) -> Line<'a> {
let a = Point::random(img_width, img_height);
let b = Point::random(img_width, img_height);
Line::new(&a, &b)
// error[E0515]: cannot return value referencing local variable `a`
// returns a value referencing data owned by the current function
}
}
Two errors occur. The first is related to the fact that the Point::new passed to Line is destroyed after Line::new is executed, so further usage is impossible. It would be possible to take it out into separate variable, but this does not meet the requirements of the usage.
The second error is related to the fact that the generated Point::random needed to build Line::random is local, which means that after Line::random is executed, it also become inaccessible.
One possible solution is to use a heap(Box<T>), but I haven't been able to figure out how to avoid destruction after the function completes.

I think your usage of references is misplaced here.
If Line must have references, I'd use a reference counted smartpointer instead.
The main problem is that if you store references in Line, Line does not own the Points. That means, you have to keep them alive externally.
This is the reason why your random constructor fails:
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
As Point::new does not take ownership of x and y, the variables x and y cease to exist at the end of the random function.
Solution
There are two ways to solve this:
Use values instead of references (e.g. make Point cloneable)
Use reference counting smart pointers
In your case, as Point is a very trivial type, I'd go with the first option:
use sandbox::{Line, Point};
fn main() {
let line = Line::new(Point::new(1, 2), Point::new(1, 2));
println!("{:?}", line);
let line2 = Line::random(10, 10);
println!("{:?}", line2);
}
use rand::Rng;
#[derive(Clone, Debug)]
pub struct Point {
pub x: i32,
pub y: i32,
}
#[derive(Clone, Debug)]
pub struct Line {
pub from: Point,
pub to: Point,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
}
impl Line {
pub fn new(from: Point, to: Point) -> Line {
Line { from, to }
}
pub fn random(img_width: i32, img_height: i32) -> Line {
let a = Point::random(img_width, img_height);
let b = Point::random(img_width, img_height);
Line::new(a, b)
}
}
Output:
Line { from: Point { x: 1, y: 2 }, to: Point { x: 1, y: 2 } }
Line { from: Point { x: 9, y: 1 }, to: Point { x: 9, y: 1 } }
Solution #2 (with reference counters)
This solution is just for reference.
As previously mentioned, it is way overkill for simple data structures, which should rather derive the Clone trait.
If you are in a multi-threaded environment, replace Rc<RefCell<Point>> with Arc<Mutex<Point>>.
use std::{cell::RefCell, rc::Rc};
use sandbox::{Line, Point};
fn main() {
let line = Line::new(
Rc::new(RefCell::new(Point::new(1, 2))),
Rc::new(RefCell::new(Point::new(1, 2))),
);
println!("{:?}", line);
let line2 = Line::random(10, 10);
println!("{:?}", line2);
}
use std::{cell::RefCell, rc::Rc};
use rand::Rng;
#[derive(Debug)]
pub struct Point {
pub x: i32,
pub y: i32,
}
#[derive(Debug)]
pub struct Line {
pub from: Rc<RefCell<Point>>,
pub to: Rc<RefCell<Point>>,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
}
impl Line {
pub fn new(from: Rc<RefCell<Point>>, to: Rc<RefCell<Point>>) -> Line {
Line { from, to }
}
pub fn random(img_width: i32, img_height: i32) -> Line {
let a = Rc::new(RefCell::new(Point::random(img_width, img_height)));
let b = Rc::new(RefCell::new(Point::random(img_width, img_height)));
Line::new(a, b)
}
}
Output:
Line { from: RefCell { value: Point { x: 1, y: 2 } }, to: RefCell { value: Point { x: 1, y: 2 } } }
Line { from: RefCell { value: Point { x: 9, y: 1 } }, to: RefCell { value: Point { x: 4, y: 8 } } }

Well, this looks like you need for the points to be sometimes referenced and sometimes owned. Rust provides Cow which comes in handy for this cases:
use rand::Rng;
use std::borrow::Cow;
#[derive(Clone)]
pub struct Point {
pub x: i32,
pub y: i32,
}
pub struct Line<'line> {
pub from: Cow<'line, Point>,
pub to: Cow<'line, Point>,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
}
impl<'line> Line<'line> {
pub fn new(from: &'line Point, to: &'line Point) -> Line<'line> {
Line { from: Cow::Borrowed(from), to: Cow::Borrowed(to)}
}
pub fn random(img_width: i32, img_height: i32) -> Line<'line> {
let a = Point::random(img_width, img_height);
let b = Point::random(img_width, img_height);
Self {
from: Cow::Owned(a),
to: Cow::Owned(b)
}
}
}
Playground
One possible solution is to use a heap(Box), but I haven't been able to figure out how to avoid destruction after the function completes.
It does not, Box are still constrain to rust borrowing rules, and unless you leak it (making the references &'static) will complain about the temporary values droped after the function scope.
About the main, you just need to bind the Points to a variable, so they will live for the scope of main:
fn main() {
let (from, to) = (Point::new(1, 2), Point::new(1, 2));
let line = Line::new(&from, &to);
line.from;
Line::random(10, 10);
}
Playground

Related

Swift: initializer 'init(_:)' requires that 'Decimal' conform to 'BinaryInteger'

I'm trying to create a function that calculates and returns compound interest. The variables are having different data types. Whenever I run the program I get an error initializer 'init(_:)' requires that 'Decimal' conform to 'BinaryInteger'. The following is my code:
import Foundation
class Compound{
var p:Double
var t:Int
var r:Double
var n:Int
var interest:Double
var amount:Double
init(p:Double,t:Int,r:Double,n:Int){
self.p = p
self.t = t
self.r = r
self.n = n
}
func calculateAmount() -> Double {
amount = p * Double(pow(Decimal(1 + (r / Double(n))),n * t))
return amount
}
}
The Error:
error: initializer 'init(_:)' requires that 'Decimal' conform to 'BinaryInteger'
amount = p * Double(pow(Decimal(1 + (r / Double(n))),n * t))
^
After looking at a similar problem I've also tried the following technique but I'm still getting the same error
func calculateAmount() -> Double {
let gg:Int = n * t
amount = p * Double(pow(Decimal(1 + (r / Double(n))),Int(truncating: gg as NSNumber) ))
return amount
}
How to solve this?
It would be easier to use the Double func pow(_: Double, _: Double) -> Double instead of using Decimal func pow(_ x: Decimal, _ y: Int) -> Decimal considering that you want to return a Double:
#discardableResult
func calculateAmount() -> Double {
amount = p * pow(1 + (r / Double(n)), Double(n) * Double(t))
return amount
}

Custom SHA256 hash calculation fails on anything but an empty String

I am trying to create my own hashing framework/library, but I've stumbled across an issue. When I calculate the SHA256 hash of an empty string, the hash is calculated successfully, but when I calculate it for anything else, it fails. Can someone help me figure out why?
As provided by Wikipedia, when performed online and using python, this hash matches.
let h = SHA256(message: Data("".utf8))
let d = h.digest()
// e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
print(d)
But 'Hello world' does not
let h = SHA256(message: Data("Hello world".utf8))
let d = h.digest()
// ce9f4c08f0688d09b8061ed6692c1d5af2516c8682fad2d9a5d72f96ba787a80
print(d)
// Expected:
// 64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c
I hope someone can help me. SHA256 implementation below:
/*
First 32 bits of the fractional parts of the
square roots of the first 8 primes 2..19.
*/
fileprivate let kSHA256H0: UInt32 = 0x6a09e667
fileprivate let kSHA256H1: UInt32 = 0xbb67ae85
fileprivate let kSHA256H2: UInt32 = 0x3c6ef372
fileprivate let kSHA256H3: UInt32 = 0xa54ff53a
fileprivate let kSHA256H4: UInt32 = 0x510e527f
fileprivate let kSHA256H5: UInt32 = 0x9b05688c
fileprivate let kSHA256H6: UInt32 = 0x1f83d9ab
fileprivate let kSHA256H7: UInt32 = 0x5be0cd19
/*
First 32 bits of the fractional parts of the
cube roots of the first 64 primes 2..311.
*/
fileprivate let kSHA256K: [UInt32] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]
/// Shift the value of x n amount to the right.
/// - Parameters:
/// - x: The value to shift.
/// - n: The amount to shift by.
/// - Returns: The shifted value.
fileprivate func shiftRight(_ x: UInt32, _ n: UInt32) -> UInt32 { x >> n }
/// Rotate the value of x n amount of times.
/// - Parameters:
/// - x: The value to rotate.
/// - y: The amount to rotate by.
/// - Returns: The rotated value.
fileprivate func rotateRight(_ x: UInt32, _ y: UInt32) -> UInt32 { (x >> (y & 31)) | (x << (32 - (y & 31))) }
/// Split data into chunks of specified size.
/// - Note: This function will not pad or append data
/// to make sure all the chunks are equal in size.
/// - Parameters:
/// - data: The data to split.
/// - size: The size of a chunk.
/// - Returns: An array containing chunks of specified size (when able).
fileprivate func chunk(_ data: Data, toSize size: Int) -> [Data] {
stride(from: 0, to: data.count, by: size).map {
data.subdata(in: $0 ..< Swift.min($0 + size, data.count))
}
}
public class SHA256 {
/// The pre-processed data.
fileprivate let message: Data
fileprivate var hash = [
kSHA256H0, kSHA256H1, kSHA256H2, kSHA256H3,
kSHA256H4, kSHA256H5, kSHA256H6, kSHA256H7
]
public init(message: Data) {
self.message = Self.preProcess(message: message)
}
fileprivate static func preProcess(message: Data) -> Data {
let L = message.count * 8 // Original message length in bits.
var K = 0 // Required padding bits.
while (L + 1 + K + 64) % 512 != 0 {
K += 1
}
var padding = Data(repeating: 0, count: K / 8)
padding.insert(0x80, at: 0) // Insert 1000 0000 into the padding.
var length = UInt64(L).bigEndian
return message + padding + Data(bytes: &length, count: 8)
}
public func digest() -> Data {
let chunks = chunk(message, toSize: 64)
for chunk in chunks {
var w = [UInt32](repeating: 0, count: 64) // 64-entry message schedule array of 32-bit words.
// Copy the chunk into first 16 words w[0..15] of the schedule array.
for i in 0 ..< 16 {
let sub = chunk.subdata(in: i ..< i + 4)
w[i] = sub.withUnsafeBytes { $0.load(as: UInt32.self) }.bigEndian
}
// Extend the first 16 words into the remaining 48 words w[16..63] of the schedule array.
for i in 16 ..< 64 {
let s0 = rotateRight(w[i - 15], 7) ^ rotateRight(w[i - 15], 18) ^ shiftRight(w[i - 15], 3)
let s1 = rotateRight(w[i - 2], 17) ^ rotateRight(w[i - 2], 19) ^ shiftRight(w[i - 2], 10)
w[i] = s1 &+ w[i - 7] &+ s0 &+ w[i - 16]
}
// Create some working variables.
var a = hash[0]
var b = hash[1]
var c = hash[2]
var d = hash[3]
var e = hash[4]
var f = hash[5]
var g = hash[6]
var h = hash[7]
// Compress function main loop.
for i in 0 ..< 64 {
let S1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25)
let ch = (e & f) ^ (~e & g)
let T1 = h &+ S1 &+ ch &+ kSHA256K[i] &+ w[i]
let S0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22)
let maj = (a & b) ^ (a & c) ^ (b & c)
let T2 = S0 &+ maj
h = g
g = f
f = e
e = d &+ T1
d = c
c = b
b = a
a = T1 &+ T2
}
hash[0] &+= a
hash[1] &+= b
hash[2] &+= c
hash[3] &+= d
hash[4] &+= e
hash[5] &+= f
hash[6] &+= g
hash[7] &+= h
}
return hash.map {
var num = $0.bigEndian
return Data(bytes: &num, count: 4)
}.reduce(Data(), +)
}
}
Turns out, I was creating the wrong sub data to construct my UInt32's from to create the message schedule array. (The first couple of lines in the .digest() function)
The old one was
let sub = chunk.subdata(in: i ..< i + 4)
The new one is
let sub = chunk.subdata(in: i * 4 ..< (i * 4) + 4)
This resolves the issue

How can I `flatmap` streams in Rust?

I have a rusoto_core::ByteStream which implements futures' Stream trait:
let chunks = vec![b"1234".to_vec(), b"5678".to_vec()];
let stream = ByteStream::new(stream::iter_ok(chunks));
I'd like to pass it to actix_web's HttpResponseBuilder::streaming method.
use actix_web::dev::HttpResponseBuilder; // 0.7.18
use rusoto_core::ByteStream; // 0.36.0
fn example(stream: ByteStream, builder: HttpResponseBuilder) {
builder.streaming(stream);
}
When I try to do it I receive the following error:
error[E0271]: type mismatch resolving `<rusoto_core::stream::ByteStream as futures::stream::Stream>::Item == bytes::bytes::Bytes`
--> src/main.rs:5:13
|
5 | builder.streaming(stream);
| ^^^^^^^^^ expected struct `std::vec::Vec`, found struct `bytes::bytes::Bytes`
|
= note: expected type `std::vec::Vec<u8>`
found type `bytes::bytes::Bytes`
I believe the reason is that streaming() expects a S: Stream<Item = Bytes, Error> (i.e., Item = Bytes) but my ByteStream has Item = Vec<u8>. How can I fix it?
I think the solution is to flatmap my ByteStream somehow but I couldn't find such a method for streams.
Here's an example how streaming() can be used:
let text = "123";
let (tx, rx_body) = mpsc::unbounded();
let _ = tx.unbounded_send(Bytes::from(text.as_bytes()));
HttpResponse::Ok()
.streaming(rx_body.map_err(|e| error::ErrorBadRequest("bad request")))
How can I flatmap streams in Rust?
A flat map converts an iterator of iterators into a single iterator (or stream instead of iterator).
Futures 0.3
Futures 0.3 doesn't have a direct flat map, but it does have StreamExt::flatten, which can be used after a StreamExt::map.
use futures::{stream, Stream, StreamExt}; // 0.3.1
fn into_many(i: i32) -> impl Stream<Item = i32> {
stream::iter(0..i)
}
fn nested() -> impl Stream<Item = i32> {
let stream_of_number = into_many(5);
let stream_of_stream_of_number = stream_of_number.map(into_many);
let flat_stream_of_number = stream_of_stream_of_number.flatten();
// Returns: 0, 0, 1, 0, 1, 2, 0, 1, 2, 3
flat_stream_of_number
}
Futures 0.1
Futures 0.1 doesn't have a direct flat map, but it does have Stream::flatten, which can be used after a Stream::map.
use futures::{stream, Stream}; // 0.1.25
fn into_many(i: i32) -> impl Stream<Item = i32, Error = ()> {
stream::iter_ok(0..i)
}
fn nested() -> impl Stream<Item = i32, Error = ()> {
let stream_of_number = into_many(5);
let stream_of_stream_of_number = stream_of_number.map(into_many);
let flat_stream_of_number = stream_of_stream_of_number.flatten();
// Returns: 0, 0, 1, 0, 1, 2, 0, 1, 2, 3
flat_stream_of_number
}
However, this doesn't solve your problem.
streaming() expects a S: Stream<Item = Bytes, Error> (i.e., Item = Bytes) but my ByteStream has Item = Vec<u8>
Yes, this is the problem. Use Bytes::from via Stream::map to convert your stream Item from one type to another:
use bytes::Bytes; // 0.4.11
use futures::Stream; // 0.1.25
fn example(stream: ByteStream, mut builder: HttpResponseBuilder) {
builder.streaming(stream.map(Bytes::from));
}

Boxed Fn requires lifetime 'static only when testing?

Using rustc 1.10.0, I'm trying to write some code which passes around boxed closures--the eventual goal is to procedurally generate an animation of fractals. Right now I have some function signatures like this:
pub fn interpolate_rectilinear(width: u32, height: u32, mut min_x: f64, mut max_x: f64, mut min_y: f64, mut max_y: f64)
-> Box<Fn(u32, u32) -> Complex64 + Send + Sync + 'static> { ... }
pub fn interpolate_stretch(width: u32, height: u32, mut min_x: f64, mut max_x: f64, mut min_y: f64, mut max_y: f64)
-> Box<Fn(u32, u32) -> Complex64 + Send + Sync + 'static> { ... }
pub fn parallel_image<F>(width: u32, height: u32, function: &F, interpolate: &Box<Fn(u32, u32) -> Complex64 + Send + Sync>, threshold: f64)
-> ImageBuffer<image::Luma<u8>, Vec<u8>>
where F: Sync + Fn(Complex64) -> Complex64
{ ... }
pub fn sequential_image<F>(width: u32, height: u32, function: &F, interpolate: &Box<Fn(u32, u32) -> Complex64>, threshold: f64)
-> ImageBuffer<image::Luma<u8>, Vec<u8>>
where F: Fn(Complex64) -> Complex64
{ ... }
Running this code for one image at a time in a binary works without problems:
let interpolate = interpolate_rectilinear(width, height, -1.0, 1.0, -1.0, 1.0);
let image = parallel_image(width * 2, height * 2, &default_julia, &interpolate, 2.0);
However, I wanted to ensure my serial and parallel image-production were both producing the same results, so I wrote the following test function:
#[test]
fn test_serial_parallel_agree() {
let (width, height) = (200, 200);
let threshold = 2.0;
let interpolate = interpolate_stretch(width, height, -1.0, 1.0, -1.0, 1.0);
assert!(parallel_image(width, height, &default_julia, &interpolate, threshold)
.pixels()
.zip(sequential_image(width, height, &default_julia, &interpolate, threshold)
.pixels())
.all(|(p, s)| p == s));
}
This refuses to compile, and I just can't figure it out. The error it gives is as follows:
> cargo test
Compiling julia-set v0.3.0
src/lib.rs:231:66: 231:78 error: mismatched types [E0308]
src/lib.rs:231 .zip(sequential_image(width, height, &default_julia, &interpolate, threshold)
^~~~~~~~~~~~
src/lib.rs:229:9: 233:36 note: in this expansion of assert! (defined in <std macros>)
src/lib.rs:231:66: 231:78 help: run `rustc --explain E0308` to see a detailed explanation
src/lib.rs:231:66: 231:78 note: expected type `&Box<std::ops::Fn(u32, u32) -> num::Complex<f64> + 'static>`
src/lib.rs:231:66: 231:78 note: found type `&Box<std::ops::Fn(u32, u32) -> num::Complex<f64> + Send + Sync>`
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
error: Could not compile `julia-set`.
I really don't know what's going on there. I don't know why I'm required to manually mark Send and Sync in the boxed return types of the interpolation functions, when the compiler typically derives those traits automatically. Still, I just kept adding in markers that the compiler suggested until things worked.
The real problem is that, while I think I have a pretty good guess why you can't just mark a boxed closure 'static, I don't know what's requiring that lifetime in this case or how to fix it.
I did guess that possibly the issue was that I was trying to reference the closure from two read-borrows at once, (which should be ok, but I was desperate); at any rate, wrapping interpolate in an Rc gives the exact same error, so that wasn't the problem.
The problem is actually here:
pub fn sequential_image<F>(
...,
interpolate: &Box<Fn(u32, u32) -> Complex64>,
...) -> ...
The interpolate doesn't expect a &Box<Fn(u32, u32) -> Complex64 + Send + Sync>, and Rust is pretty bad at handling variance through all of this complexity.
One solution is to do the cast where it's called:
sequential_image(width, height, &default_julia,
&(interpolate as Box<Fn(u32, u32) -> Complex64>),
threshold)
but this requires a value case of sequential_image and is pretty damn ugly.
A nicer way is to just fix the parameter of sequential_image to something both more general and something easier for the compiler to reason about: basic pointers.
pub fn sequential_image<F>(
...,
interpolate: &Fn(u32, u32) -> Complex64,
...) -> ...
Now you can call it with just
sequential_image(width, height, &default_julia,
&*interpolate,
threshold)
and the compiler can do all of the variance magic itself.

How to Typecast in Swift?

I'm working on a custom path for UIBezierPath, and I'm getting the "Cannot assign a value of type (CGFloat) to a value of type CGFloat." I think it's because there is some issue with typecasting? How can I fix this? The warnings are popping up for the "X = (b2 - b1) / (m1 - m2)" line and "Y = m1 * X + b1" line.
func lineIntersection(m1: CGFloat, b1: CGFloat, m2: CGFloat, b2: CGFloat, inout X: CGFloat, inout Y: CGFloat) -> Bool {
if m1 == m2 {
return false
} else if X = (b2 - b1)/(m1 - m2) {
return true
} else if Y = m1 * X + b1 {
return true
} else {
return false
}
}
I'll be calling this function in another function later on
func xxx() {
var outX = CGFloat()
var outY = CGFloat()
lineIntersection(oldSlope, b1: oldIntercept, m2: newSlope, b2: newIntercept, X: &outX, Y: &outY)
}
Swift doesn't have zero as a "false" value, you need to explicitly compare with != 0 in the ifs. Also, move the assignments to separate lines instead of doing it as part of the condition.
Floating point equality comparisons are not reliable except in a few special cases, and this is not likely to be one of them.
I would remove the inout parameters and return an optional CGPoint, i.e., -> CGPoint?. Return nil for false, and the CGPoint intersection for true.
Resulting function (I've removed the equality checks altogether; the floating point division by zero is not dangerous, we can check for Inf/NaN later):
func lineIntersection(m1 m1: CGFloat, b1: CGFloat, m2: CGFloat, b2: CGFloat) -> CGPoint? {
let x = (b2 - b1) / (m1 - m2)
let y = m1 * x + b1
return y.isFinite ? CGPoint(x: x, y: y) : nil
}
Use at the calling location would be something like:
if let intersection = lineIntersection(m1: m1, b1: b1, m2: m2, b2: b2) {
// use intersection.x and intersection.y
}
As for the literal question of how to typecast (although this was not the issue here), you can init even "basic types" with something like CGFloat(value), which results in a type conversion by "creating" a new CGFloat from value. Several types also have alternative ways to specify how exactly the conversion happens, e.g., Int32(truncatingBitPattern: largerInteger) takes the lowest 32 bits as they are, whereas just Int32(largerInteger) would crash if it over- or underflows. Casting as such is done with as (known to succeed at compile time), as? (try casting at runtime, nil on failure), as! (try casting at runtime, assert success).

Resources