<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def from_euler_angles(alpha_beta_gamma, beta=None, gamma=None):
 """Improve your life drastically Assumes the Euler angles correspond to the quaternion R via R = exp(alpha*z/2) * exp(beta*y/2) * exp(gamma*z/2) The angles naturally must be in radians for this to make any sense. NOTE: Before opening an issue reporting something "wrong" with this function, be sure to read all of the following page, *especially* the very last section about opening issues or pull requests. <https://github.com/moble/quaternion/wiki/Euler-angles-are-horrible> Parameters alpha_beta_gamma: float or array of floats This argument may either contain an array with last dimension of size 3, where those three elements describe the (alpha, beta, gamma) radian values for each rotation; or it may contain just the alpha values, in which case the next two arguments must also be given. beta: None, float, or array of floats If this array is given, it must be able to broadcast against the first and third arguments. gamma: None, float, or array of floats If this array is given, it must be able to broadcast against the first and second arguments. Returns ------- R: quaternion array The shape of this array will be the same as the input, except that the last dimension will be removed. """

    # Figure out the input angles from either type of input
    if gamma is None:
        alpha_beta_gamma = np.asarray(alpha_beta_gamma, dtype=np.double)
        alpha = alpha_beta_gamma[..., 0]
        beta  = alpha_beta_gamma[..., 1]
        gamma = alpha_beta_gamma[..., 2]
    else:
        alpha = np.asarray(alpha_beta_gamma, dtype=np.double)
        beta  = np.asarray(beta, dtype=np.double)
        gamma = np.asarray(gamma, dtype=np.double)

    # Set up the output array
    R = np.empty(np.broadcast(alpha, beta, gamma).shape + (4,), dtype=np.double)

    # Compute the actual values of the quaternion components
    R[..., 0] =  np.cos(beta/2)*np.cos((alpha+gamma)/2)  # scalar quaternion components
    R[..., 1] = -np.sin(beta/2)*np.sin((alpha-gamma)/2)  # x quaternion components
    R[..., 2] =  np.sin(beta/2)*np.cos((alpha-gamma)/2)  # y quaternion components
    R[..., 3] =  np.cos(beta/2)*np.sin((alpha+gamma)/2)  # z quaternion components

    return as_quat_array(R)