본문 바로가기

학교 공부/프로그래밍원리

HW 3- (2) reshape 구현하기

Vector 에 대한 reshape 구현이다.

추후에 수정할거 있으면 수정해보기!!! (오류 검토 못해봄)

val a:Vector = new Vector(Array(1,2,3,4,5,6))

//i번째 인덱스부터 n개씩 나눠진 Array 반환하기
def sep(i:Int,n:Int):Array[Float]

def func(x:Array[Float], shape:Int*):NDArray= {
  def sep(i:Int,n:Int,res:Array[Float]=Array()):Array[Float] ={
    if(n==0) res
    else sep(i+1,n-1,res ++ Array(x(i)))
  }

  if(shape.length ==1) new Vector(x)
  else if (shape.length ==2) {
    val res:Array[Vector] = Array()
    for(x<- 1to shape(0)) {
      val a = new Vector(sep((x-1)*shape(1),shape(1)))
      res ++ Array(a)
    }
    //res 는 Array(Vector)
    new Matrix(res)
  }
  else {
    //3차원 이상은 수정하기
    new Vector(x)
  }
}

 

 

다음은 reduceLeft 이다.

  
  /**
   * Apply an element-wise binary operator to all elements along the first axis.
   * Note that f can be non-associative.
   *
   * e.g) [[2, 3, 5], [3, 1, 0]].reduceLeft(_ + _) = [5, 4, 5]
   * [[1, 2, 3]].reduceLeft(_ + _) = [1, 2, 3]
   * [2, 3, 4].reduceLeft(_ - _) = ((2 - 3) - 4) = -5
   *
   * @param f binary operator
   * @tparam T type of the inner element: NDArray (if this is Matrix or StackedArray) or Float (if this is Vector)
   * @return see Seq.reduceLeft
   */
  def reduceLeft[T](f: (Float, Float) => Float): T = ???

 

 * Apply an element-wise binary operator to all elements along the first axis.
   * Note that f can be non-associative.
   * e.g) 

예시 코드를 분석해보니 shape(0) 갯수만큼이 연산을 거치는 원소들.

   * [[2, 3, 5], [3, 1, 0]].reduceLeft(_ + _) = [5, 4, 5]

해석 ) shape = (2,3) 인 Matrix

 

   * [[1, 2, 3]].reduceLeft(_ + _) = [1, 2, 3]

해석 ) shape = (1,3)인 Matrix


   * [2, 3, 4].reduceLeft(_ - _) = ((2 - 3) - 4) = -5

해석 ) shape = (3)인 Vector
   *
   * @param f binary operator
   * @tparam T type of the inner element: NDArray (if this is Matrix or StackedArray) or Float (if this is Vector)
   * @return see Seq.reduceLeft
   */

 

 

근데 지금은 벡터의 연산을 구현하는 것이므로 벡터, reduceLeft만 구현하면 된다. 

  def reduceLeft[T](f: (Float, Float) => Float): T = ???
// [2, 3, 4].reduceLeft(_ - _) = ((2 - 3) - 4) = -5
// [2, 3, 4].reduceLeft(_ - _) = ((2 - 3) - 4) = -5
def reduceLeft[T](f: (Float, Float) => Float): T = {
def func(arr:Array[Float],idx:Int = 0,res:Float =0):Float ={
	if (idx == arr.length) res
	else func(arr,idx+1,f(res,arr(idx)))
}
func(this.values)
}

이렇게 코드 짜봤더니 func(this.values)가 T type이 아니고 Float type이라고 빨간줄 긋고 지랄한다...

  * @tparam T type of the inner element: NDArray (Matrix or StackedArray) or Float (if this is Vector)

그럼 이건 뭔데....

 

 

  def reduceLeft[T](f: (Float, Float) => Float): T = {
    val a:Array[T] = Array()
    def func(arr: Array[Float], idx: Int = 0, res: Float = 0): Float = {
      if (idx == arr.length) res
      else func(arr, idx + 1, f(res, arr(idx)))
    }
    a ++ Array(func(this.values))
    a(0)
  }

이렇게 고치니까 고요해졌긴한데 조금 더 지켜봐야겠다.....

 

 

 

 

 

unary operaion 구현하는 코드

def unaryOp(f: Float => Float): NDArray = {
    val original: Array[Float] = this.values
    def update(idx: Int, res: Array[Float]): Array[Float] = {
      if (idx == original.length) res
      else {
        res(idx) = f(res(idx))
        update(idx + 1, res)
      }
    }
    val result:Vector = new Vector(update(0,original))
    result
  }
  
  
 def binOp(f: (Float, Float) => Float, that: NDArray): NDArray = {
    val original:Array[Float] = this.values
    def update(idx:Int, res:Array[Float]):Array[Float] ={
      if(idx == original.length) res
      else {
        res(idx) = f(that.get(idx),res(idx))
        update(idx+1,res)
      }
    }
    if(that.ndim != 1) throw new NNException("dims are not same")
    else{
      val result = new Vector(update(0,original))
      result
    }
  }



def equals(that: NDArray): Boolean = {
    def check(idx: Int): Boolean = {
      if (idx >= values.length) true
      else {
        if (values(idx) != that.get(idx)) false
        else check(idx + 1)
      }
    }
    check(0)
  }

 

 

일단 Vector.scala 는 마무리

... Matrix.scala 로 가보자