Mathematical functions in Swift - swift

How do I use mathematical functions like sqrt(), floor(), round(), sin(), etc?
When doing:
_ = floor(2.0)
_ = sqrt(2.0)
I get:
error: use of unresolved identifier 'floor'
error: use of unresolved identifier 'sqrt'

As other noted you have several options. If you want only mathematical functions. You can import only Darwin.
import Darwin
If you want mathematical functions and other standard classes and functions. You can import Foundation.
import Foundation
If you want everything and also classes for user interface, it depends if your playground is for OS X or iOS.
For OS X, you need import Cocoa.
import Cocoa
For iOS, you need import UIKit.
import UIKit
You can easily discover your playground platform by opening File Inspector (⌥⌘1).

To be perfectly precise, Darwin is enough. No need to import the whole Cocoa framework.
import Darwin
Of course, if you need elements from Cocoa or Foundation or other higher level frameworks, you can import them instead

For people using swift [2.2] on Linux i.e. Ubuntu, the import is different!
The correct way to do this is to use Glibc. This is because on OS X and iOS, the basic Unix-like API's are in Darwin but in linux, these are located in Glibc. Importing Foundation won't help you here because it doesn't make the distinction by itself. To do this, you have to explicitly import it yourself:
#if os(macOS) || os(iOS)
import Darwin
#elseif os(Linux) || CYGWIN
import Glibc
#endif
You can follow the development of the Foundation framework here to learn more
EDIT: December 26th, 2018
As pointed out by #Cœur, starting from swift 3.0 some math functions are now part of the types themselves. For example, Double now has a squareRoot function. Similarly, ceil, floor, round, can all be achieved with Double.rounded(FloatingPointRoundingRule) -> Double.
Furthermore, I just downloaded and installed the latest stable version of swift on Ubuntu 18.04, and it looks like Foundation framework is all you need to import to have access to the math functions now. I tried finding documentation for this, but nothing came up.
➜ swift
Welcome to Swift version 4.2.1 (swift-4.2.1-RELEASE). Type :help for assistance.
1> sqrt(9)
error: repl.swift:1:1: error: use of unresolved identifier 'sqrt'
sqrt(9)
^~~~
1> import Foundation
2> sqrt(9)
$R0: Double = 3
3> floor(9.3)
$R1: Double = 9
4> ceil(9.3)
$R2: Double = 10

You can use them right inline:
var square = 9.4
var floored = floor(square)
var root = sqrt(floored)
println("Starting with \(square), we rounded down to \(floored), then took the square root to end up with \(root)")

To use the math-functions you have to import Cocoa
You can see the other defined mathematical functions in the following way.
Make a Cmd-Click on the function name sqrt and you enter the file with all other global math functions and constanst.
A small snippet of the file
...
func pow(_: CDouble, _: CDouble) -> CDouble
func sqrtf(_: CFloat) -> CFloat
func sqrt(_: CDouble) -> CDouble
func erff(_: CFloat) -> CFloat
...
var M_LN10: CDouble { get } /* loge(10) */
var M_PI: CDouble { get } /* pi */
var M_PI_2: CDouble { get } /* pi/2 */
var M_SQRT2: CDouble { get } /* sqrt(2) */
...

For the Swift way of doing things, you can try and make use of the tools available in the Swift Standard Library. These should work on any platform that is able to run Swift.
Instead of floor(), round() and the rest of the rounding routines you can use rounded(_:):
let x = 6.5
// Equivalent to the C 'round' function:
print(x.rounded(.toNearestOrAwayFromZero))
// Prints "7.0"
// Equivalent to the C 'trunc' function:
print(x.rounded(.towardZero))
// Prints "6.0"
// Equivalent to the C 'ceil' function:
print(x.rounded(.up))
// Prints "7.0"
// Equivalent to the C 'floor' function:
print(x.rounded(.down))
// Prints "6.0"
These are currently available on Float and Double and it should be easy enough to convert to a CGFloat for example.
Instead of sqrt() there's the squareRoot() method on the FloatingPoint protocol. Again, both Float and Double conform to the FloatingPoint protocol:
let x = 4.0
let y = x.squareRoot()
For the trigonometric functions, the standard library can't help, so you're best off importing Darwin on the Apple platforms or Glibc on Linux. Fingers-crossed they'll be a neater way in the future.
#if os(OSX) || os(iOS)
import Darwin
#elseif os(Linux)
import Glibc
#endif
let x = 1.571
print(sin(x))
// Prints "~1.0"

Related

Importing an objective-c enum from a swift file?

I'm trying to import an objective-c enum to use in a swift file. To do so, my enum is defined as follows:
typedef NS_ENUM(NSUInteger, UBESearchType) {
UBESearchTypeGlobal = 0,
UBESearchTypeInStoreSearch = 1
};
In my swift file I import the library it correponds to: import LegacyModelsObjc.
I try referencing the enum UBESearchTypeGlobal but I get an error which says Cannot find UBESearchTypeGlobal in scope. Any idea why this error might be happening?
I'm a fool.
In swift you need to specify the namespace of the enum rather than the name of it.
So I had to do UBESearchType.global to access it

How do you format floats into strings in Swift 5?

I am trying to format a float into a string with a set number of digits. All the examples I have seen use something like this:
let thisString = String(format: "%2.4f" , 3.14159262)
However, when I try this I get:
Argument labels '(format:, _:)' do not match any available overloads
. Like it doesn't even recognize "format" as a valid way to initialize a string. I am using Swift 5 on Xcode 10.2 on Mojave, if that makes a difference. Am I missing some framework or something? Did the initializer change?
Your code should be working correctly. Can you please try the following:
import Foundation
let firstString = String(format: "%2.4f", arguments: [3.14159262])
print(firstString)
let secondString = String(format: "%2.4f", 3.14159262)
print(secondString)
I have this code running fine in a playground using Swift 5.
Removing the Foundation import gives the same error you described in your question.

Conditional Conformance to Hashable

With Xcode 10, and Swift 4.2 there are additional types that conform to Hashable as long as their elements also conform to Hashable (Array, Dictionary, etc).
I currently have some code in my project to add Hashable conformance for Swift 4.1 and below like this:
extension Array: Hashable where Element: Hashable {
public var hashValue: Int {
let prime = 31
var result = 1
for element in self {
result = prime * result + element.hashValue
}
return result
}
}
However, even if I add #if !swift(>=4.2) around the code I still see the same warning in Xcode.
My question is, how can I keep the conditional conformance to Hashable for Swift 4.1 and below, but silence the warning for Swift 4.2?
The conditional compilation statement #if swift(...) checks against the language version you're running with – which can differ from the compiler (and therefore standard library) version.
In your case, it sounds like you're using a Swift 4.2 compiler in Swift 4 compatibility mode, which gives you a language version of 4.1.50. This therefore passes the conditional compilation statement and your extension is compiled, giving you a duplicate conformance.
In order to check for a compiler version less than 4.2, you want the following:
// less than 4.2 in Swift 4 compat mode and (less than 4.2 in 3 compat mode or
// greater than 4).
#if !swift(>=4.1.50) && (!swift(>=3.4) || swift(>=4.0))
extension Array : Hashable where Element : Hashable {
public var hashValue: Int {
let prime = 31
var result = 1
for element in self {
result = prime * result + element.hashValue
}
return result
}
}
#endif
Things will be much better with the new #if compiler directive, which is available in Swift 4.2 from Xcode 10 beta 4 onwards (confirmed by #MartinR). With that, you can directly test for the compiler version, ignoring any compatibility modes it might be running in.
This doesn't help your specific case as you need the code to be understood by both Swift 4.2 and 4.1 compilers (as also pointed out by Martin), but for future compatibility problems, you could for example use #if !compiler(>=5) in order to only compile a block of code if using a 4.2 compiler.

Swift 3.2 - compiler doesn't let me use the Darwin.kevent global function

This was working in Swift 3.1, however once I switched to Xcode 9 it stopped compiling. Here's a sample code:
let kq: Int32 = 0
let changelist: UnsafePointer<kevent>! = nil
let nchanges: Int32 = 0
let eventlist: UnsafeMutablePointer<kevent>! = nil
let nevents: Int32 = 0
let timeout: UnsafePointer<timespec>! = nil
Darwin.kevent(kq, changelist, nchanges, eventlist, nevents, timeout)
Error is
error: missing argument labels 'ident:filter:flags:fflags:data:udata:' in call
The problems seems to be caused by the fact that the Darwin module exports both a struct an a function with the same name - kevent, and the compiler doesn't choose the global function and instead wants me to add the struct initializer labels, which doesn't work for me as the parameters lists don't match.
The kevent struct initalizer looks like this
public init(ident: UInt, filter: Int16, flags: UInt16, fflags: UInt32, data: Int, udata: UnsafeMutableRawPointer!)
I even tried declaring all arguments as local variables (as in the sample code), in order to make sure there is no type inference that would make the function call incorrect which could cause the compiler to think that I wanted to use the struct. No luck.
Does anybody know a solution to this "overloading" issue?
I cannot tell you why the fully qualified function name does not compile with Swift 3.2, but
kevent(kq, changelist, nchanges, eventlist, nevents, timeout)
without the Darwin prefix compiles without problems (tested with Xcode 9 GM, Swift 3.2 and Swift 4).
I can confirm that
Darwin.kevent(kq, changelist, nchanges, eventlist, nevents, timeout)
compiles with Swift 3.1 (Xcode 8.3.3), so you might want to file a bug
report.

How can one use XCTAssertNil with optional structs?

Update 3/23/2016 I just tested my original sample code below and it all compiles fine in XCode 7.3. Looks like XCTAssertNil was updated along the way to take an expression of type () throws -> Any? Therefore this question and answer may be no longer needed (except for a while with older versions of the compiler.)
I'm writing my first unit tests in XCode with XCTest. I'm unsure how one can take advantage of XCTAssertNil as it seems to only compile when using certain types. It appears it will work with optionals made from classes and built-in primitives, but not structs. How would one go about using this method?
For structs the compiler gives the following error (assuming 'SimpleStruct' is the name of your type):
'SimpleStruct' is not identical to 'AnyObject'
Here's a simple test class to illustrate some of the types that compile okay and other's that don't.
import Cocoa
import XCTest
struct SimpleStruct {
}
class SimpleClass {
}
class Tests: XCTestCase {
func testl() {
var simpleStruct:SimpleStruct? = nil;
var simpleClass:SimpleClass? = nil;
var i:Int? = nil;
var s:String? = nil;
var tuple:(Int,String)? = nil;
XCTAssertNil(simpleStruct); // compile error
XCTAssertNil(simpleClass); // OK
XCTAssertNil(i); // OK
XCTAssertNil(s); // OK
XCTAssertNil(tuple); // compile error
}
}
Update 3/23/2016 Updated for XCode 7.3 (however if you see my edit to the question, it would appear this workaround is no longer needed)
Here is a workaround. I created my own generic function:
func AssertNil<T>(#autoclosure expression: () -> T?, message: String = "",
file: StaticString = #file, line: UInt = #line) {
if (expression() != nil) {
XCTFail(message, file:file, line:line)
}
}
Doesn't seem like this should be necessary. Is this just a result of XCTest originally targeting Objective-C and not being updated/bridged enough for Swift yet?
Edit: I've done enough research to see that AnyObject can be used to represent any class but not structs. However, that then doesn't explain why the code in my original post compiles for Int types and String types. (I read somewhere else that Xcode may auto convert these to NSNumber and NSString for you which might explain why. See http://www.scottlogic.com/blog/2014/09/24/swift-anyobject.html and http://www.drewag.me/posts/swift-s-weird-handling-of-basic-value-types-and-anyobject. I'll try removing my import of Cocoa which imports Foundation to see what happens)
Edit2: XCTest also imports Foundation so I can't test what I wanted to. I could create my own methods and test this. For now, I assume that the auto-conversions are what are allowing the int and string optionals to compile. Seems like XCTest isn't quite ready for prime time with Swift.
Update 8/13/2015: Edited the function to be compatible with XCode 7 beta