Skip to content

Instantly share code, notes, and snippets.

@jhaberstro
jhaberstro / gist:878f7f2043f922f0d06c
Last active August 29, 2015 14:02
Multiple optional bindings in Swift (i.e. the equivalent of if let (a, b, c) = (optA, optB, optC) { ... })
// The DSL's implementation (i.e. just the applicative interface for Optionals + methods for creating tuples)
operator infix <*> { associativity left }
@infix func <*><A, B>(lhs: (A -> B)?, rhs: A?) -> B? {
switch lhs {
case .None:
return .None
case let .Some(f):
return rhs.map(f)
}
}
@jhaberstro
jhaberstro / signextend.cpp
Created July 18, 2015 04:38
Nifty sign extend
template< unsigned SrcSize, unsigned DstSize >
static inline uint32_t signExtend(uint32_t x)
{
static_assert(SrcSize <= 32, "SrcSize cannot be larger than 32 bits.");
static_assert(SrcSize <= 32, "DstSize cannot be larger than 32 bits.");
static_assert(SrcSize < DstSize, "DstSize must be larger than SrcSize.");
constexpr unsigned src_mask = (1 << SrcSize) - 1;
constexpr unsigned extension = ((1 << (DstSize - SrcSize)) - 1) << SrcSize;
uint32_t result = x & src_mask;
uint32_t is_signed = (x & (1 << (SrcSize - 1))) >> (SrcSize - 1);
#define CONSTANTHASH_DEPTH 64
// randomly generated constants. The bottom half has to be FFFF or
// else the entire hash loses some strength
static const size_t CONSTANTHASH_CONSTANTS[CONSTANTHASH_DEPTH+1] =
{
0x6157FFFF, 0x5387FFFF, 0x8ECBFFFF, 0xB3DBFFFF, 0x1AFDFFFF, 0xD1FDFFFF, 0x19B3FFFF, 0xE6C7FFFF,
0x53BDFFFF, 0xCDAFFFFF, 0xE543FFFF, 0x369DFFFF, 0x8135FFFF, 0x50E1FFFF, 0x115BFFFF, 0x07D1FFFF,
0x9AA1FFFF, 0x4D87FFFF, 0x442BFFFF, 0xEAA5FFFF, 0xAEDBFFFF, 0xB6A5FFFF, 0xAFE9FFFF, 0xE895FFFF,
0x4E05FFFF, 0xF8BFFFFF, 0xCB5DFFFF, 0x2F85FFFF, 0xF1DFFFFF, 0xD5ADFFFF, 0x438DFFFF, 0x6073FFFF,
@jhaberstro
jhaberstro / prob_data_miners_notes.md
Last active September 29, 2015 00:20
Notes for "Probability for Data Miners"

========================

  • "P(A)" means the probability that the event A will happen/A will be true.
  • The core axioms
    1. 0 <= P(A) <= 1
    2. P(true) = 1
    3. P(false) = 0
    4. P(A or B) = P(A) + P(B) - P(A and B) Note: it seems that this is definition of or is the exclusive or.
  • From the core axioms, we can derive:
@jhaberstro
jhaberstro / monoid.swift
Last active December 14, 2015 18:39
Swift monoid, num, Sum typeclasses with Int32 instances
protocol Monoid {
class func mzero() -> Self
func mop(y: Self) -> Self
}
func mconcat<M : Monoid>(t: Array<M>) -> M {
return (t.reduce(M.mzero()) { $0.mop($1) })
}
protocol Num {
@jhaberstro
jhaberstro / gist:7795350
Last active December 30, 2015 07:19
Graphics Architecture Readings
object main
{
val coins = Array(1, 5, 10, 25)
val minCoin = coins.reduceLeft (_ min _)
var table: Map[Int, Seq[Int]] = Map()
val infinity: Seq[Int] = for (i <- 1 to 100000) yield i
def calculateMinCoins(n: Int): Seq[Int] = {
if (n == 0) { Seq() }
@jhaberstro
jhaberstro / jaguar_optimization_notes.md
Last active April 10, 2016 01:13
"Taming the Jaguar x86 Optimization at Insomniac Games" Notes

Taming the Jaguar x86 Optimization at Insomniac Games

  • When the branch predictor is wrong and speculatively executes code from a branch that is not taken, that can actually pollute caches, causing much worse performance than just wasted cycles from fetch, decode, ALU.
  • Retiring: all instructions retire (commit) in program order and happens at a max rate of 2/cycle.
    • i.e. the visible side-effects of an instruction are committed in order, even if executed out of order.
  • L1 hit takes 3 cycle, L2 hit takes 25 cycles, i.e. L2 is ~8x slower.
  • Main memory ~200 cycles, i.e. around 66x slower than L1
  • Retire control unit (RCU) can only store 64 instructions.
  • L2 miss + full RCU can be a recipe for disaster:
    • L2 miss will not retire for 200+ cycles and frontend is (almost) always fetching 2 instructions / cycle, which means after ~32 instructions the RCU is full and so the entire pipeline must stall. CPU can no longer (out of order) execute instructions that occur after the memory op to hide that memory
@jhaberstro
jhaberstro / compiler_optimize_atomics.md
Created May 22, 2016 19:23
"N4455 No Sane Compiler Would Optimize Atomics" notes

Showcases some interesting and non-obvious optimizations that compilers can make on and around atomics. In particular, I liked this example: the following code

int x = 0;
std::atomic<int> y;
int dso() {
  x = 0;
  int z = y.load(std::memory_order_seq_cst);
  y.store(0, std::memory_order_seq_cst);
  x = 1;
 return z;
@jhaberstro
jhaberstro / num.swift
Last active June 3, 2016 12:17
Swift typeclass example
protocol Num {
class func zero() -> Self
func succ() -> Self
func add(y: Self) -> Self
func multiply(y: Self) -> Self
}
extension Int32: Num {
static func zero() -> Int32 { return 0 }
func succ() -> Int32 { return self + 1 }